clear merging conflict
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\NitloadIndustry\\\u7814\u7A76\u9879\u76EE\\1-Flagship\\TH2020\\ProjectFile\\\u5185\u6838\u6E90\u4EE3\u7801\\StgSharp\\",
|
||||
"Documents": [],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"Version": 1,
|
||||
"WorkspaceRootPath": "D:\\NitloadIndustry\\\u7814\u7A76\u9879\u76EE\\1-Flagship\\TH2020\\ProjectFile\\\u5185\u6838\u6E90\u4EE3\u7801\\StgSharp\\",
|
||||
"Documents": [],
|
||||
"DocumentGroupContainers": [
|
||||
{
|
||||
"Orientation": 0,
|
||||
"VerticalTabListWidth": 256,
|
||||
"DocumentGroups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="CachePool.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Graphics.OpenGL;
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Commom.Collections
|
||||
{
|
||||
/*
|
||||
public interface IPoolItem<TSignature>
|
||||
{
|
||||
|
||||
public int ID
|
||||
{
|
||||
get;
|
||||
init;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class CacheIndexPool<TSignature, TItem> : IEnumerable<TItem>
|
||||
where TItem: IPoolItem<TSignature>
|
||||
{
|
||||
|
||||
public CacheIndexPool(
|
||||
Func<TSignature>
|
||||
) { }
|
||||
|
||||
}
|
||||
/**/
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Class1.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Geometries.SpaceGeometry
|
||||
{
|
||||
internal class Class1 { }
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IGraphicAPIs.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Graphics
|
||||
{
|
||||
public interface IGraphicAPIs
|
||||
{
|
||||
|
||||
public IntPtr GraphicApiPackageHandle
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IRegisterType.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public interface IRegisterType
|
||||
{
|
||||
|
||||
public ref T AsRef<T>() where T: unmanaged, INumber<T>;
|
||||
|
||||
public ref T Member<T>(int index) where T: unmanaged, INumber<T>;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="BufferStack.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
[CollectionBuilder(typeof(BufferStackBuilder), nameof(BufferStackBuilder.Create))]
|
||||
public unsafe class BufferStack<T> : IDisposable where T: unmanaged
|
||||
{
|
||||
|
||||
private byte* _buffer;
|
||||
private ulong _count;
|
||||
|
||||
public BufferStack(int capacity)
|
||||
{
|
||||
if (capacity <= 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(capacity));
|
||||
}
|
||||
|
||||
AllocateBuffer(capacity);
|
||||
}
|
||||
|
||||
public int Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => (int)_count;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Clear()
|
||||
{
|
||||
((Header*)_buffer)->Top = 0;
|
||||
_count = 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Dispose()
|
||||
{
|
||||
Marshal.FreeHGlobal((nint)_buffer);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public T Pop()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
if (header->Top == 0) {
|
||||
throw new InvalidOperationException("Stack underflow");
|
||||
}
|
||||
|
||||
header->Top--;
|
||||
_count--;
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
return dataStart[header->Top];
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Push(T item)
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
if (header->Top >= header->Capacity) {
|
||||
Expand();
|
||||
}
|
||||
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
dataStart[header->Top] = item;
|
||||
header->Top++;
|
||||
_count++;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public bool TryPop(out T value)
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
if (header->Top == 0)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
header->Top--;
|
||||
_count--;
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
value = dataStart[header->Top];
|
||||
return true;
|
||||
}
|
||||
|
||||
// Internal method for efficient bulk initialization
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal unsafe void InitializeFromSpan(ReadOnlySpan<T> span)
|
||||
{
|
||||
if (span.IsEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Header* header = (Header*)_buffer;
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
|
||||
fixed (T* sourcePtr = span) {
|
||||
Buffer.MemoryCopy(sourcePtr, dataStart,
|
||||
header->Capacity * (nuint)sizeof(T),
|
||||
(nuint)span.Length * (nuint)sizeof(T));
|
||||
}
|
||||
|
||||
header->Top = (nuint)span.Length;
|
||||
_count = (ulong)span.Length;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void AllocateBuffer(int capacity)
|
||||
{
|
||||
nuint size = (nuint)sizeof(Header) + ((nuint)capacity * (nuint)sizeof(T));
|
||||
_buffer = (byte*)NativeMemory.Alloc(size);
|
||||
Header* header = (Header*)_buffer;
|
||||
header->Top = 0;
|
||||
header->Capacity = (nuint)capacity;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void Expand()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
nuint newCap = header->Capacity * 2;
|
||||
nuint newSize = (nuint)sizeof(Header) + newCap * (nuint)sizeof(T);
|
||||
_buffer = (byte*)NativeMemory.Realloc(_buffer, newSize);
|
||||
header = (Header*)_buffer;
|
||||
header->Capacity = newCap;
|
||||
}
|
||||
|
||||
private struct Header
|
||||
{
|
||||
|
||||
public nuint Capacity;
|
||||
public nuint Top;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,291 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="ConcurrentBufferStack.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public static class BufferStackBuilder
|
||||
{
|
||||
|
||||
// For BufferStack collection builder
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static BufferStack<T> Create<T>(ReadOnlySpan<T> span) where T: unmanaged
|
||||
{
|
||||
if (span.IsEmpty)
|
||||
{
|
||||
return new BufferStack<T>(4); // Default small capacity
|
||||
}
|
||||
|
||||
BufferStack<T> stack = new BufferStack<T>(span.Length);
|
||||
|
||||
|
||||
// Use internal method for efficient bulk initialization
|
||||
stack.InitializeFromSpan(span);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
// For ConcurrentBufferStack collection builder
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static ConcurrentBufferStack<T> CreateConcurrent<T>(ReadOnlySpan<T> span) where T: unmanaged
|
||||
{
|
||||
if (span.IsEmpty)
|
||||
{
|
||||
return new ConcurrentBufferStack<T>(4); // Default small capacity
|
||||
}
|
||||
|
||||
ConcurrentBufferStack<T> stack = new ConcurrentBufferStack<T>(span.Length);
|
||||
|
||||
|
||||
// Use internal method for efficient bulk initialization
|
||||
stack.InitializeFromSpan(span);
|
||||
|
||||
return stack;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[CollectionBuilder(builderType: typeof(BufferStackBuilder), methodName: nameof(BufferStackBuilder.CreateConcurrent))]
|
||||
public unsafe class ConcurrentBufferStack<T> : IDisposable where T: unmanaged
|
||||
{
|
||||
|
||||
private byte* _buffer;
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private ulong _count;
|
||||
|
||||
public ConcurrentBufferStack(int capacity)
|
||||
{
|
||||
if (capacity <= 0) {
|
||||
throw new ArgumentOutOfRangeException(nameof(capacity));
|
||||
}
|
||||
|
||||
AllocateBuffer(capacity);
|
||||
}
|
||||
|
||||
public ulong Count
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Volatile.Read(ref _count);
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
header->Top = 0;
|
||||
Volatile.Write(ref _count, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_lock.Dispose();
|
||||
Marshal.FreeHGlobal((nint)_buffer);
|
||||
}
|
||||
|
||||
public T Pop()
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
while (true)
|
||||
{
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
if (oldTop <= 0) {
|
||||
throw new InvalidOperationException("Stack underflow");
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop - 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
_ = Interlocked.Decrement(ref _count);
|
||||
return dataStart[oldTop - 1];
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
public void Push(T item)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
_lock.EnterMetaDataRead();
|
||||
try
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
nuint cap = Volatile.Read(ref header->Capacity);
|
||||
if (oldTop >= cap)
|
||||
{
|
||||
_lock.ExitMetaDataRead();
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
header = (Header*)_buffer;
|
||||
if (header->Top >= header->Capacity)
|
||||
{
|
||||
nuint newCap = header->Capacity * 2;
|
||||
nuint newSize = (nuint)sizeof(Header) + (newCap * (nuint)sizeof(T));
|
||||
|
||||
_lock.EnterBufferCopy();
|
||||
try
|
||||
{
|
||||
_buffer = (byte*)NativeMemory.Realloc(_buffer, newSize);
|
||||
((Header*)_buffer)->Capacity = newCap;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferCopy();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop + 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
dataStart[oldTop] = item;
|
||||
_ = Interlocked.Increment(ref _count);
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsThreadReadingMetaData) {
|
||||
_lock.ExitMetaDataRead();
|
||||
}
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryPop(out T value)
|
||||
{
|
||||
Header* header = (Header*)_buffer;
|
||||
while (true)
|
||||
{
|
||||
nuint oldTop = Volatile.Read(ref header->Top);
|
||||
if (oldTop <= 0)
|
||||
{
|
||||
value = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Interlocked.CompareExchange(ref header->Top, oldTop - 1, oldTop) == oldTop)
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
try
|
||||
{
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
value = dataStart[oldTop - 1];
|
||||
_ = Interlocked.Decrement(ref _count);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
Thread.Sleep(0); // Yield to avoid busy waiting
|
||||
}
|
||||
}
|
||||
|
||||
// Internal method for efficient bulk initialization
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
internal unsafe void InitializeFromSpan(ReadOnlySpan<T> span)
|
||||
{
|
||||
if (span.IsEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Header* header = (Header*)_buffer;
|
||||
T* dataStart = (T*)(_buffer + sizeof(Header));
|
||||
|
||||
fixed (T* sourcePtr = span) {
|
||||
Buffer.MemoryCopy(sourcePtr, dataStart,
|
||||
header->Capacity * (nuint)sizeof(T),
|
||||
(nuint)span.Length * (nuint)sizeof(T));
|
||||
}
|
||||
|
||||
header->Top = (nuint)span.Length;
|
||||
Volatile.Write(ref _count, (ulong)span.Length);
|
||||
}
|
||||
|
||||
private void AllocateBuffer(int capacity)
|
||||
{
|
||||
nuint size = (nuint)sizeof(Header) + ((nuint)capacity * (nuint)sizeof(T));
|
||||
_buffer = (byte*)NativeMemory.Alloc(size);
|
||||
Header* header = (Header*)_buffer;
|
||||
header->Top = 0;
|
||||
header->Capacity = (nuint)capacity;
|
||||
}
|
||||
|
||||
private struct Header
|
||||
{
|
||||
|
||||
public nuint Capacity; // max capacity of the stack (number of elements)
|
||||
public nuint Top; // next available index in the stack
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -61,6 +61,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
return new hlsfHandle(handle, size);
|
||||
}
|
||||
|
||||
fallback:
|
||||
i = level;
|
||||
s = segmentIndex;
|
||||
while (!TryPopLevelForAllocation(i, s, out handle))
|
||||
@@ -76,7 +77,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
throw new OverflowException("Out of memory: Unable to allocate new 16MB block or find suitable bucket for allocation.");
|
||||
}
|
||||
|
||||
break;
|
||||
Thread.Sleep(0);
|
||||
goto fallback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,23 +86,26 @@ namespace StgSharp.HighPerformance.Memory
|
||||
SliceMemory(handle, (segmentIndex + 1) * levelSizeArray[level]);
|
||||
}
|
||||
|
||||
return new hlsfHandle(handle, size);
|
||||
return new hlsfHandle(handle, size);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseEntryNextLock(handle);
|
||||
}
|
||||
}
|
||||
|
||||
private void SliceMemory(Entry* e, int offset)
|
||||
{
|
||||
Entry* current = e;
|
||||
ulong n = e->NextNear;
|
||||
Entry* next = (Entry*)n;
|
||||
Entry* next = e;
|
||||
|
||||
ulong originOffset = e->Position - (ulong)m_Buffer;
|
||||
ulong finalOffset = originOffset + (ulong)offset;
|
||||
ulong end = e->Position + e->Size - (ulong)m_Buffer;
|
||||
int remainSize = (int)(e->Size - offset);
|
||||
|
||||
if ((originOffset & 63) != 0) {
|
||||
throw new InvalidOperationException("Entry position offset is not aligned to 64 bytes.");
|
||||
}
|
||||
AcquireEntryNextLock(e);
|
||||
AcquireEntryPrevLock(next);
|
||||
|
||||
int minLevel = Math.Max((BitOperations.TrailingZeroCount(finalOffset) - 6) / 2, 0);
|
||||
int i = minLevel >= levelSizeArray.Length ? levelSizeArray.Length - 1 : minLevel;
|
||||
@@ -112,9 +117,13 @@ namespace StgSharp.HighPerformance.Memory
|
||||
int blockCount = (int)((ulong.Min(board, end) - board) / (ulong)levelSize);
|
||||
if (blockCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int s = blockCount * levelSize;
|
||||
int levelSize = levelSizeArray[i];
|
||||
int blockCount = remainSize / levelSize % 4;
|
||||
if (blockCount == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
int s = blockCount * levelSize;
|
||||
|
||||
// create and init new entry
|
||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||
@@ -123,12 +132,24 @@ namespace StgSharp.HighPerformance.Memory
|
||||
BucketNode* bucket = (BucketNode*)newEntry->Position;
|
||||
bucket->EntryRef = newEntry;
|
||||
|
||||
// link new entry
|
||||
newEntry->PreviousNear = (ulong)current;
|
||||
newEntry->NextNear = n;
|
||||
current->NextNear = (ulong)newEntry;
|
||||
if (next != null) {
|
||||
// link new entry
|
||||
newEntry->PreviousNear = (ulong)current;
|
||||
newEntry->NextNear = n;
|
||||
current->NextNear = (ulong)newEntry;
|
||||
next->PreviousNear = (ulong)newEntry;
|
||||
|
||||
newEntry->Level = i;
|
||||
PushLevel(i, blockCount - 1, bucket);
|
||||
|
||||
// set new entry
|
||||
Entry* old = current;
|
||||
current = newEntry;
|
||||
|
||||
// update lock and data
|
||||
finalOffset += (ulong)s;
|
||||
remainSize -= s;
|
||||
ReleaseEntryNextLock(old);
|
||||
AcquireEntryNextLock(current);
|
||||
}
|
||||
|
||||
newEntry->Level = i;
|
||||
@@ -183,8 +204,63 @@ namespace StgSharp.HighPerformance.Memory
|
||||
remainSize -= s;
|
||||
if (remainSize <= 0)
|
||||
{
|
||||
break;
|
||||
ReleaseEntryNextLock(current);
|
||||
ReleaseEntryPrevLock(next);
|
||||
return;
|
||||
}
|
||||
for (; i >= 0; i--)
|
||||
{
|
||||
int levelSize = levelSizeArray[i];
|
||||
int blockCount = remainSize / levelSize % 4;
|
||||
if (blockCount == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int s = blockCount * levelSize;
|
||||
|
||||
// create and init new entry
|
||||
Entry* newEntry = (Entry*)_entries.Allocate();
|
||||
newEntry->LockBuffer = 0;
|
||||
newEntry->Position = (nuint)((ulong)m_Buffer + finalOffset);
|
||||
newEntry->Size = (uint)s;
|
||||
BucketNode* bucket = (BucketNode*)newEntry->Position;
|
||||
bucket->EntryRef = newEntry;
|
||||
bucket->LockBuffer = 0;
|
||||
newEntry->State = EntryState.ThreadOccupied;
|
||||
|
||||
// link new entry
|
||||
newEntry->PreviousNear = (ulong)current;
|
||||
current->NextNear = (ulong)newEntry;
|
||||
newEntry->NextNear = n;
|
||||
next->PreviousNear = (ulong)newEntry;
|
||||
|
||||
newEntry->Level = i;
|
||||
PushLevel(i, blockCount - 1, bucket);
|
||||
|
||||
// set new entry
|
||||
Entry* old = current;
|
||||
current = newEntry;
|
||||
|
||||
// update lock and data
|
||||
finalOffset += (ulong)s;
|
||||
remainSize -= s;
|
||||
ReleaseEntryNextLock(old);
|
||||
AcquireEntryNextLock(current);
|
||||
if (remainSize <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Release locks in reverse order
|
||||
ReleaseEntryNextLock(current);
|
||||
ReleaseEntryPrevLock(next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,13 +275,22 @@ namespace StgSharp.HighPerformance.Memory
|
||||
/// </returns>
|
||||
private bool TryAllocateNew16MBBlock(out Entry* handle)
|
||||
{
|
||||
nuint pos = _spareMemory->Position;
|
||||
nuint pos = Volatile.Read(ref _spareMemory->Position);
|
||||
nuint blockSize = (nuint)levelSizeArray[^1] * 2; // Use last level size (16MB)
|
||||
nuint newPos = pos + blockSize;
|
||||
|
||||
ulong p = _spareMemory->PreviousNear;
|
||||
Entry* previous = (Entry*)p;
|
||||
|
||||
ulong p;
|
||||
Entry* previous;
|
||||
do
|
||||
{
|
||||
p = Volatile.Read(ref _spareMemory->PreviousNear);
|
||||
previous = (Entry*)p;
|
||||
if (previous != null) {
|
||||
AcquireEntryNextLock(previous);
|
||||
}
|
||||
AcquireEntryPrevLock(_spareMemory);
|
||||
break;
|
||||
} while (true);
|
||||
if (_spareMemory->Size <= 0)
|
||||
{
|
||||
handle = null;
|
||||
@@ -225,20 +310,34 @@ namespace StgSharp.HighPerformance.Memory
|
||||
handle->Size = (uint)blockSize;
|
||||
handle->Level = GetLevelFromSize((uint)blockSize);
|
||||
|
||||
// Update spare memory position
|
||||
_spareMemory->Position = newPos;
|
||||
BucketNode* b = (BucketNode*)handle->Position;
|
||||
b->EntryRef = handle;
|
||||
PushLevel(handle->Level, DetermineSegmentIndex((uint)blockSize, handle->Level), b);
|
||||
handle->PrevLock = 0;
|
||||
handle->NextLock = 0;
|
||||
|
||||
// update position linked list
|
||||
handle->NextNear = (ulong)_spareMemory;
|
||||
handle->PreviousNear = p;
|
||||
_spareMemory->PreviousNear = (ulong)handle;
|
||||
if (previous != null) {
|
||||
previous->NextNear = (ulong)handle;
|
||||
// Update spare memory position
|
||||
_spareMemory->Position = newPos;
|
||||
BucketNode* b = (BucketNode*)handle->Position;
|
||||
b->EntryRef = handle;
|
||||
PushLevel(handle->Level, DetermineSegmentIndex((uint)blockSize, handle->Level), b);
|
||||
|
||||
// update position linked list
|
||||
handle->NextNear = (ulong)_spareMemory;
|
||||
handle->PreviousNear = p;
|
||||
_spareMemory->PreviousNear = (ulong)handle;
|
||||
if (previous != null) {
|
||||
previous->NextNear = (ulong)handle;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
handle = null;
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseEntryNextLock(previous);
|
||||
ReleaseEntryPrevLock(_spareMemory);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -39,6 +39,12 @@ namespace StgSharp.HighPerformance.Memory
|
||||
public unsafe partial class HybridLayerSegregatedFitAllocator
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AcquireBucketNodeSpinLock(BucketNode* node)
|
||||
{
|
||||
AcquireBucketNodeBothLocks(node);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize bucket system (called in constructor)
|
||||
/// </summary>
|
||||
@@ -47,16 +53,6 @@ namespace StgSharp.HighPerformance.Memory
|
||||
_bucketHeads = new ulong[levelSizeArray.Length * 3];
|
||||
}
|
||||
|
||||
#region BucketNode Operations
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsNullOrEmpty(BucketNode* node)
|
||||
{
|
||||
return node == null || node->Magic != BucketNode.MAGIC_NUMBER;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void PushLevel(int levelIndex, int sizeIndex, BucketNode* node)
|
||||
{
|
||||
if (node == null || node->EntryRef == null) {
|
||||
@@ -64,112 +60,269 @@ namespace StgSharp.HighPerformance.Memory
|
||||
}
|
||||
|
||||
int index = (3 * levelIndex) + sizeIndex;
|
||||
if (_bucketHeads[index] == EmptyHandle)
|
||||
if (Interlocked.CompareExchange(ref _bucketHeads[index], (nuint)node, EmptyHandle) == EmptyHandle)
|
||||
{
|
||||
_bucketHeads[index] = (nuint)node;
|
||||
node->IsInBucket = true;
|
||||
node->Magic = BucketNode.MAGIC_NUMBER;
|
||||
node->NextLevel = EmptyHandle;
|
||||
node->PreviousLevel = EmptyHandle;
|
||||
return;
|
||||
} else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
AcquireBucketNodeNextLock(node);
|
||||
ulong head = Volatile.Read(ref _bucketHeads[index]);
|
||||
node->NextLevel = head;
|
||||
BucketNode* headNode = (BucketNode*)head;
|
||||
|
||||
try
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _bucketHeads[index], (nuint)node, head) == head)
|
||||
{
|
||||
if (headNode != null && !TryAcquireBucketNodePrevLock(headNode))
|
||||
{
|
||||
// reset state and retry
|
||||
_ = Interlocked.CompareExchange(ref _bucketHeads[index], head, (nuint)node);
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
try
|
||||
{
|
||||
node->IsInBucket = true;
|
||||
node->Magic = BucketNode.MAGIC_NUMBER;
|
||||
if (headNode != null) {
|
||||
headNode->PreviousLevel = (ulong)node;
|
||||
}
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (headNode != null) {
|
||||
ReleaseBucketNodePrevLock(headNode);
|
||||
}
|
||||
}
|
||||
} else
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseBucketNodeNextLock(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Add to head of linked list
|
||||
ulong head = _bucketHeads[index];
|
||||
BucketNode* headNode = (BucketNode*)head;
|
||||
|
||||
node->NextLevel = head;
|
||||
node->PreviousLevel = EmptyHandle;
|
||||
node->IsInBucket = true;
|
||||
node->Magic = BucketNode.MAGIC_NUMBER;
|
||||
|
||||
if (headNode != null) {
|
||||
headNode->PreviousLevel = (ulong)node;
|
||||
/// <summary>
|
||||
/// 根据锁类型释放BucketNode锁
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseBucketNodeLockByType(BucketNode* node, byte lockType)
|
||||
{
|
||||
switch (lockType)
|
||||
{
|
||||
case 0:
|
||||
ReleaseBucketNodePrevLock(node);
|
||||
return; // PrevLock
|
||||
case 1:
|
||||
ReleaseBucketNodeBothLocks(node);
|
||||
return; // BothLocks
|
||||
case 2:
|
||||
ReleaseBucketNodeNextLock(node);
|
||||
return; // NextLock
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_bucketHeads[index] = (nuint)node;
|
||||
/// <summary>
|
||||
/// 按地址顺序释放BucketNode锁
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseOrderedBucketLocks(BucketNode* previous, BucketNode* node, BucketNode* next)
|
||||
{
|
||||
if (previous != null) {
|
||||
ReleaseBucketNodeNextLock(previous);
|
||||
}
|
||||
if (node != null) {
|
||||
ReleaseBucketNodeBothLocks(node);
|
||||
}
|
||||
if (next != null) {
|
||||
ReleaseBucketNodePrevLock(next);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveFromBucket(int levelIndex, int sizeIndex, BucketNode* node)
|
||||
{
|
||||
int index = (3 * levelIndex) + sizeIndex;
|
||||
|
||||
if ((BucketNode*)_bucketHeads[index] == node)
|
||||
while (true)
|
||||
{
|
||||
_bucketHeads[index] = EmptyHandle;
|
||||
return;
|
||||
}
|
||||
if ((BucketNode*)Volatile.Read(ref _bucketHeads[index]) == node)
|
||||
{
|
||||
if (TryPopLevel(levelIndex, sizeIndex, out _)) {
|
||||
return;
|
||||
}
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ulong p = node->PreviousLevel;
|
||||
ulong n = node->NextLevel;
|
||||
BucketNode* previous = (BucketNode*)p;
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
ulong p = Volatile.Read(ref node->PreviousLevel);
|
||||
ulong n = Volatile.Read(ref node->NextLevel);
|
||||
BucketNode* previous = (BucketNode*)p;
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
|
||||
if (previous != null) {
|
||||
previous->NextLevel = n;
|
||||
}
|
||||
if (next != null) {
|
||||
next->PreviousLevel = p;
|
||||
}
|
||||
if (!TryAcquireOrderedBucketLocks(previous, node, next))
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
node->NextLevel = EmptyHandle;
|
||||
node->PreviousLevel = EmptyHandle;
|
||||
node->IsInBucket = false;
|
||||
try
|
||||
{
|
||||
if (Volatile.Read(ref node->PreviousLevel) != p || Volatile.Read(ref node->NextLevel) != n)
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (previous != null) {
|
||||
previous->NextLevel = n;
|
||||
}
|
||||
if (next != null) {
|
||||
next->PreviousLevel = p;
|
||||
}
|
||||
|
||||
node->NextLevel = EmptyHandle;
|
||||
node->PreviousLevel = EmptyHandle;
|
||||
node->IsInBucket = false;
|
||||
return;
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseOrderedBucketLocks(previous, node, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireBucketNodeSpinLock(BucketNode* node)
|
||||
{
|
||||
return TryAcquireBucketNodeBothLocks(node);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireOrderedBucketLocks(BucketNode* previous, BucketNode* node, BucketNode* next)
|
||||
{
|
||||
if (previous != null && node != null && next != null)
|
||||
{
|
||||
// previous -> node -> next
|
||||
return TryAcquireBucketNodeNextLock(previous) &&
|
||||
TryAcquireBucketNodeBothLocks(node) &&
|
||||
TryAcquireBucketNodePrevLock(next);
|
||||
} else if (previous != null && node != null) {
|
||||
return TryAcquireBucketNodeNextLock(previous) && TryAcquireBucketNodeBothLocks(node);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryPopLevel(int levelIndex, int sizeIndex, out BucketNode* node)
|
||||
{
|
||||
int index = (3 * levelIndex) + sizeIndex;
|
||||
ulong h = _bucketHeads[index];
|
||||
BucketNode* head = (BucketNode*)h;
|
||||
|
||||
if (head == null)
|
||||
while (true)
|
||||
{
|
||||
node = null;
|
||||
return false;
|
||||
ulong h = Volatile.Read(ref _bucketHeads[index]);
|
||||
BucketNode* head = (BucketNode*)h;
|
||||
|
||||
if (head == null)
|
||||
{
|
||||
node = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!TryAcquireBucketNodeNextLock(head))
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
ulong n = Volatile.Read(ref head->NextLevel);
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
|
||||
if (next == null)
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _bucketHeads[index], EmptyHandle, h) == h)
|
||||
{
|
||||
node = head;
|
||||
return true;
|
||||
}
|
||||
node = null;
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
if (!TryAcquireBucketNodePrevLock(next))
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _bucketHeads[index], head->NextLevel, h) == h)
|
||||
{
|
||||
node = head;
|
||||
node->IsInBucket = false;
|
||||
node->NextLevel = EmptyHandle;
|
||||
if (next != null) {
|
||||
next->PreviousLevel = EmptyHandle;
|
||||
}
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
Thread.Sleep(0);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (next != null) {
|
||||
ReleaseBucketNodePrevLock(next);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ReleaseBucketNodeNextLock(head);
|
||||
}
|
||||
}
|
||||
|
||||
ulong n = head->NextLevel;
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
|
||||
if (next == null)
|
||||
{
|
||||
_bucketHeads[index] = EmptyHandle;
|
||||
node = head;
|
||||
node->IsInBucket = false;
|
||||
node->NextLevel = EmptyHandle;
|
||||
node->PreviousLevel = EmptyHandle;
|
||||
return true;
|
||||
}
|
||||
|
||||
_bucketHeads[index] = head->NextLevel;
|
||||
node = head;
|
||||
node->IsInBucket = false;
|
||||
node->NextLevel = EmptyHandle;
|
||||
|
||||
if (next != null) {
|
||||
next->PreviousLevel = EmptyHandle;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool TryRemoveFromBucket(int levelIndex, int sizeIndex, BucketNode* node)
|
||||
{
|
||||
int index = (3 * levelIndex) + sizeIndex;
|
||||
if ((BucketNode*)_bucketHeads[index] == node)
|
||||
if ((BucketNode*)Volatile.Read(ref _bucketHeads[index]) == node)
|
||||
{
|
||||
_bucketHeads[index] = EmptyHandle;
|
||||
return true;
|
||||
if (TryPopLevel(levelIndex, sizeIndex, out _)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong p = Volatile.Read(ref node->PreviousLevel);
|
||||
ulong n = Volatile.Read(ref node->NextLevel);
|
||||
BucketNode* previous = (BucketNode*)p;
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
|
||||
if (!TryAcquireOrderedBucketLocks(previous, node, next)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
ulong p = node->PreviousLevel;
|
||||
ulong n = node->NextLevel;
|
||||
BucketNode* previous = (BucketNode*)p;
|
||||
BucketNode* next = (BucketNode*)n;
|
||||
if (Volatile.Read(ref node->PreviousLevel) != p || Volatile.Read(ref node->NextLevel) != n) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (previous != null) {
|
||||
previous->NextLevel = n;
|
||||
@@ -183,9 +336,9 @@ namespace StgSharp.HighPerformance.Memory
|
||||
node->IsInBucket = false;
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
finally
|
||||
{
|
||||
return false;
|
||||
ReleaseOrderedBucketLocks(previous, node, next);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -193,7 +346,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
/// BucketNode structure - specialized node for bucket linked lists Stored in main
|
||||
/// allocation area (user-overwritable region)
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = 32)]
|
||||
[StructLayout(LayoutKind.Explicit, Size = 40)]
|
||||
internal struct BucketNode
|
||||
{
|
||||
|
||||
@@ -201,12 +354,149 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
[FieldOffset(16)] internal Entry* EntryRef; // Pointer to corresponding Entry
|
||||
[FieldOffset(28)] internal bool IsInBucket; // Whether in bucket
|
||||
[FieldOffset(36)] internal int NextLock;
|
||||
[FieldOffset(32)] internal int PrevLock;
|
||||
[FieldOffset(24)] internal uint Magic; // Magic number verification
|
||||
[FieldOffset(32)] internal ulong LockBuffer;
|
||||
|
||||
[FieldOffset(0)] internal ulong NextLevel; // Bucket stack linked list: next pointer
|
||||
[FieldOffset(8)] internal ulong PreviousLevel; // Bucket stack linked list: previous pointer
|
||||
|
||||
}
|
||||
|
||||
#region BucketNode Operations
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool IsNullOrEmpty(BucketNode* node)
|
||||
{
|
||||
return node == null || node->Magic != BucketNode.MAGIC_NUMBER;
|
||||
}
|
||||
|
||||
// BucketNode 前驱锁操作(控制PreviousLevel字段)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireBucketNodePrevLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
return Interlocked.CompareExchange(ref node->PrevLock, thread, 0) == 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AcquireBucketNodePrevLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
if (Volatile.Read(ref node->PrevLock) != thread)
|
||||
{
|
||||
while (Interlocked.CompareExchange(ref node->PrevLock, thread, 0) != 0) {
|
||||
Thread.Sleep(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseBucketNodePrevLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
if (Volatile.Read(ref node->PrevLock) == thread) {
|
||||
Volatile.Write(ref node->PrevLock, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// BucketNode 后继锁操作(控制NextLevel字段)
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireBucketNodeNextLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
return Interlocked.CompareExchange(ref node->NextLock, thread, 0) == 0;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AcquireBucketNodeNextLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
if (Volatile.Read(ref node->NextLock) != thread)
|
||||
{
|
||||
while (Interlocked.CompareExchange(ref node->NextLock, thread, 0) != 0) {
|
||||
Thread.Sleep(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseBucketNodeNextLock(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
int thread = Environment.CurrentManagedThreadId;
|
||||
if (Volatile.Read(ref node->NextLock) == thread) {
|
||||
Volatile.Write(ref node->NextLock, 0);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireBucketNodeBothLocks(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (TryAcquireBucketNodePrevLock(node))
|
||||
{
|
||||
if (TryAcquireBucketNodeNextLock(node))
|
||||
{
|
||||
return true;
|
||||
} else
|
||||
{
|
||||
ReleaseBucketNodePrevLock(node); // 回滚
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseBucketNodeBothLocks(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseBucketNodePrevLock(node);
|
||||
ReleaseBucketNodeNextLock(node);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AcquireBucketNodeBothLocks(BucketNode* node)
|
||||
{
|
||||
if (node == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
AcquireBucketNodePrevLock(node);
|
||||
AcquireBucketNodeNextLock(node);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,44 +41,6 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
private object _lock = new object();
|
||||
|
||||
public void DisplayAllocatedEntryLayout(bool singleStep)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Entry* cur = _spareMemory;
|
||||
while (cur != null)
|
||||
{
|
||||
if (cur->State == EntryState.Allocated)
|
||||
{
|
||||
Console.WriteLine(EntryToString(cur));
|
||||
if (singleStep) {
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
cur = (Entry*)cur->PreviousNear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DisplayEmptyEntryLayout(bool singleStep)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
Entry* cur = _spareMemory;
|
||||
while (cur != null)
|
||||
{
|
||||
if (cur->State == EntryState.Empty)
|
||||
{
|
||||
Console.WriteLine(EntryToString(cur));
|
||||
if (singleStep) {
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
cur = (Entry*)cur->PreviousNear;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void DisplayEntryLayout(bool singleStep)
|
||||
{
|
||||
lock (_lock)
|
||||
|
||||
@@ -28,6 +28,13 @@
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using hlsfHandle = StgSharp.HighPerformance.Memory.HybridLayerSegregatedFitAllocationHandle;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
@@ -47,6 +54,13 @@ namespace StgSharp.HighPerformance.Memory
|
||||
if (e == null) {
|
||||
return;
|
||||
}
|
||||
AcquireEntrySpinLock(e);
|
||||
try
|
||||
{
|
||||
if (GetEntryState(e) != EntryState.Allocated) {
|
||||
return;
|
||||
}
|
||||
SetEntryState(e, EntryState.ThreadOccupied);
|
||||
|
||||
if (e->State != EntryState.Allocated) {
|
||||
return;
|
||||
|
||||
@@ -41,18 +41,24 @@ namespace StgSharp.HighPerformance.Memory
|
||||
public unsafe partial class HybridLayerSegregatedFitAllocator
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void AcquireEntrySpinLock(Entry* entry)
|
||||
{
|
||||
AcquireEntryBothLocks(entry);
|
||||
}
|
||||
|
||||
private bool AssertBackwardBoundary(ulong current, Entry* target, int level)
|
||||
{
|
||||
ulong align = (ulong)levelSizeArray[level + 1];
|
||||
ulong targetOffset = target->Position - (ulong)m_Buffer;
|
||||
return current / align == targetOffset / align;
|
||||
int size = (level * 2) + 6;
|
||||
ulong align = current >> size;
|
||||
return align == target->Position >> size && align == (current + target->Size) >> size;
|
||||
}
|
||||
|
||||
private bool AssertForwardBoundary(ulong current, Entry* target, int level)
|
||||
{
|
||||
ulong align = (ulong)levelSizeArray[level + 1];
|
||||
ulong targetOffset = target->Position + target->Size - (ulong)m_Buffer;
|
||||
return current / align == targetOffset / align;
|
||||
int size = (level * 2) + 6;
|
||||
ulong align = current >> size;
|
||||
return align == target->Position >> size && align == (current - target->Size) >> size;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -77,7 +83,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
/// <summary>
|
||||
/// Used in Free operations, efficiently remove from buckets and merge adjacent blocks.
|
||||
/// Current Entry will serve as the final merged block.
|
||||
/// Current Entry will serve as the final merged block. The Merge will be in lazy
|
||||
/// strategy, any fail in acquiring spin lock will end a merging process.
|
||||
/// </summary>
|
||||
private void MergeAndRemoveFromBuckets(Entry* entry)
|
||||
{
|
||||
@@ -85,6 +92,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
return;
|
||||
}
|
||||
|
||||
Entry* result = entry;
|
||||
uint size = entry->Size;
|
||||
int originLevel = GetLevelFromSize(size);
|
||||
int segment = DetermineSegmentIndex(size, originLevel);
|
||||
@@ -154,7 +162,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
private void RecycleEntry(Entry* entry)
|
||||
{
|
||||
if (entry == null) {
|
||||
if (entry is null) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -163,29 +171,45 @@ namespace StgSharp.HighPerformance.Memory
|
||||
_entries.Free((nuint)entry);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void ReleaseEntrySpinLock(Entry* entry)
|
||||
{
|
||||
ReleaseEntryBothLocks(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove node from position linked list
|
||||
/// </summary>
|
||||
private void RemoveFromPositionChain(Entry* entry)
|
||||
{
|
||||
if (entry == null) {
|
||||
return;
|
||||
}
|
||||
AcquireEntrySpinLock(entry);
|
||||
try
|
||||
{
|
||||
Entry* prev = (Entry*)entry->PreviousNear;
|
||||
Entry* next = (Entry*)entry->NextNear;
|
||||
|
||||
Entry* prev = (Entry*)entry->PreviousNear;
|
||||
Entry* next = (Entry*)entry->NextNear;
|
||||
if (prev != null) {
|
||||
prev->NextNear = entry->NextNear;
|
||||
}
|
||||
if (next != null) {
|
||||
next->PreviousNear = entry->PreviousNear;
|
||||
}
|
||||
|
||||
if (prev != null) {
|
||||
prev->NextNear = entry->NextNear;
|
||||
// Clear node pointers
|
||||
entry->NextNear = EmptyHandle;
|
||||
entry->PreviousNear = EmptyHandle;
|
||||
_entries.Free((nuint)entry);
|
||||
}
|
||||
if (next != null) {
|
||||
next->PreviousNear = entry->PreviousNear;
|
||||
finally
|
||||
{
|
||||
ReleaseEntrySpinLock(entry);
|
||||
}
|
||||
}
|
||||
|
||||
// Clear node pointers
|
||||
entry->NextNear = EmptyHandle;
|
||||
entry->PreviousNear = EmptyHandle;
|
||||
_entries.Free((nuint)entry);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static bool TryAcquireEntrySpinLock(Entry* entry)
|
||||
{
|
||||
return TryAcquireEntryBothLocks(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -198,6 +222,7 @@ namespace StgSharp.HighPerformance.Memory
|
||||
|
||||
[FieldOffset(28)] internal int Level; // Level of the block in the allocator
|
||||
[FieldOffset(24)] internal uint Size; // Block size information
|
||||
[FieldOffset(32)] internal ulong LockBuffer;
|
||||
[FieldOffset(8)] internal ulong NextNear; // Position linked list: next pointer
|
||||
[FieldOffset(16)] internal ulong PreviousNear; // Position linked list: previous pointer
|
||||
[FieldOffset(32)] public EntryState State;
|
||||
|
||||
@@ -66,6 +66,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
_spareMemory->PreviousNear = EmptyHandle;
|
||||
_spareMemory->NextNear = EmptyHandle;
|
||||
_spareMemory->Position = (nuint)m_Buffer;
|
||||
_spareMemory->PrevLock = 0;
|
||||
_spareMemory->NextLock = 0;
|
||||
_spareMemory->Size = (uint)byteSize;
|
||||
}
|
||||
|
||||
@@ -87,6 +89,8 @@ namespace StgSharp.HighPerformance.Memory
|
||||
_spareMemory->PreviousNear = EmptyHandle;
|
||||
_spareMemory->NextNear = EmptyHandle;
|
||||
_spareMemory->Position = (nuint)m_Buffer;
|
||||
_spareMemory->PrevLock = 0;
|
||||
_spareMemory->NextLock = 0;
|
||||
_spareMemory->Size = (uint)byteSize;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="ISlabAllocatable.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public interface ISlabAllocatable { }
|
||||
}
|
||||
@@ -0,0 +1,271 @@
|
||||
# HLSF (Hybrid Layer Segregated Fit) Allocator
|
||||
|
||||
A high-performance, O(1) memory allocator designed for real-time applications that demand predictable allocation and deallocation performance.
|
||||
|
||||
## Overview
|
||||
|
||||
The Hybrid Layer Segregated Fit (HLSF) allocator is a sophisticated memory management system that combines the benefits of segregated free lists with layered size classification. It provides constant-time allocation and deallocation operations while maintaining excellent memory utilization and low fragmentation.
|
||||
|
||||
## Key Features
|
||||
|
||||
### Performance Characteristics
|
||||
- **O(1) Time Complexity**: Both allocation and deallocation operations execute in constant time
|
||||
- **High Throughput**: Capable of handling millions of operations per second
|
||||
- **Low Latency**: Predictable performance suitable for real-time applications
|
||||
- **Excellent Deallocation Speed**: Superior free performance compared to traditional allocators
|
||||
|
||||
### Memory Management
|
||||
- **External Metadata Storage**: All allocation metadata is stored in external SLAB allocators, keeping the main allocation area clean
|
||||
- **Native Byte Alignment Control**: Configurable alignment (minimum 16 bytes) with hardware-optimized defaults
|
||||
- **Large Block Support**: Single allocation limit of 32MB per request
|
||||
- **Efficient Memory Utilization**: Low overhead with intelligent block merging
|
||||
|
||||
### Architecture
|
||||
- **10-Level Hierarchy**: Size classes from 64 bytes to 16MB (64, 256, 1KB, 4KB, 16KB, 64KB, 256KB, 1MB, 4MB, 16MB)
|
||||
- **3-Segment Segregation**: Each level is divided into 3 segments for better size distribution
|
||||
- **Hybrid Approach**: Combines best aspects of segregated fit and layered allocation strategies
|
||||
|
||||
## Architecture Details
|
||||
|
||||
### Size Classification System
|
||||
|
||||
The allocator uses a logarithmic size classification system with 10 levels:
|
||||
|
||||
```
|
||||
Level 0: 64 bytes (2^6)
|
||||
Level 1: 256 bytes (2^8)
|
||||
Level 2: 1KB (2^10)
|
||||
Level 3: 4KB (2^12)
|
||||
Level 4: 16KB (2^14)
|
||||
Level 5: 64KB (2^16)
|
||||
Level 6: 256KB (2^18)
|
||||
Level 7: 1MB (2^20)
|
||||
Level 8: 4MB (2^22)
|
||||
Level 9: 16MB (2^24)
|
||||
```
|
||||
|
||||
Each level follows the pattern: `size = 64 * 4^level`
|
||||
|
||||
### Bucket Organization
|
||||
|
||||
Each size level is further divided into 3 segments based on exact size requirements:
|
||||
- **Segment 0**: 1x level size
|
||||
- **Segment 1**: 2x level size
|
||||
- **Segment 2**: 3x level size
|
||||
|
||||
This provides fine-grained size matching while maintaining O(1) lookup performance.
|
||||
|
||||
### External Metadata Design
|
||||
|
||||
Unlike traditional allocators that embed metadata within allocated blocks, HLSF stores all metadata externally:
|
||||
|
||||
- **Entry Structure (36 bytes)**: Contains position, size, level, and linkage information
|
||||
- **BucketNode Structure (32 bytes)**: Manages free block organization with integrity verification
|
||||
- **SLAB Storage**: Both structures are allocated from separate SLAB allocators for optimal cache performance
|
||||
|
||||
This design provides several advantages:
|
||||
- Clean allocation areas free from metadata corruption
|
||||
- Better cache locality for metadata operations
|
||||
- Simplified debugging and memory inspection
|
||||
- No metadata overhead in allocated blocks
|
||||
|
||||
## Performance Benchmarks
|
||||
|
||||
*Note: The following results are from informal testing and should be considered preliminary.*
|
||||
|
||||
### Single-threaded Performance (65,536 operations)
|
||||
|
||||
| Operation | Average Time | Throughput | Performance Rating |
|
||||
|-----------|--------------|------------|-------------------|
|
||||
| Allocation | 31-40ms | ~2M allocs/sec | Good |
|
||||
| Free | 2-3ms | ~25M frees/sec | Excellent |
|
||||
|
||||
**Test Configuration:**
|
||||
- Pool Size: 16MB
|
||||
- Block Sizes: 64-1024 bytes (mixed)
|
||||
- Platform: x64, .NET 8
|
||||
- Iterations: 5 rounds
|
||||
|
||||
### Memory Efficiency
|
||||
|
||||
- **Metadata Overhead**: ~2.8% of total allocation
|
||||
- **Alignment**: 16-byte default (configurable)
|
||||
- **Fragmentation**: Low due to intelligent merging algorithms
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Allocation
|
||||
|
||||
```csharp
|
||||
// Create allocator with 64MB pool
|
||||
using var allocator = new HybridLayerSegregatedFitAllocator(64 * 1024 * 1024);
|
||||
|
||||
// Allocate 1KB block
|
||||
var handle = allocator.Alloc(1024);
|
||||
|
||||
// Use the allocated memory
|
||||
Span<byte> memory = handle.BufferHandle;
|
||||
memory[0] = 42;
|
||||
|
||||
// Free the block
|
||||
allocator.Free(handle);
|
||||
```
|
||||
|
||||
### Custom Alignment
|
||||
|
||||
```csharp
|
||||
// Create allocator with 32-byte alignment
|
||||
using var allocator = new HybridLayerSegregatedFitAllocator(
|
||||
byteSize: 32 * 1024 * 1024,
|
||||
align: 32
|
||||
);
|
||||
|
||||
var handle = allocator.Alloc(256);
|
||||
// Memory is guaranteed to be 32-byte aligned
|
||||
```
|
||||
|
||||
### Bulk Operations
|
||||
|
||||
```csharp
|
||||
var handles = new List<HybridLayerSegregatedFitAllocationHandle>();
|
||||
|
||||
// Allocate multiple blocks
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
handles.Add(allocator.Alloc((uint)(64 + i % 960))); // 64-1023 bytes
|
||||
}
|
||||
|
||||
// Free all blocks
|
||||
foreach (var handle in handles)
|
||||
{
|
||||
allocator.Free(handle);
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### HybridLayerSegregatedFitAllocator
|
||||
|
||||
Main allocator class providing memory management functionality.
|
||||
|
||||
#### Constructors
|
||||
|
||||
```csharp
|
||||
public HybridLayerSegregatedFitAllocator(nuint byteSize)
|
||||
public HybridLayerSegregatedFitAllocator(nuint byteSize, int align)
|
||||
```
|
||||
|
||||
#### Methods
|
||||
|
||||
```csharp
|
||||
public HybridLayerSegregatedFitAllocationHandle Alloc(uint size)
|
||||
public void Free(HybridLayerSegregatedFitAllocationHandle handle)
|
||||
public void Dispose()
|
||||
```
|
||||
|
||||
### HybridLayerSegregatedFitAllocationHandle
|
||||
|
||||
Handle representing an allocated memory block.
|
||||
|
||||
#### Properties
|
||||
|
||||
```csharp
|
||||
public readonly byte* Pointer { get; }
|
||||
public readonly Span<byte> BufferHandle { get; }
|
||||
public readonly uint AllocSize { get; }
|
||||
public readonly ref byte this[int index] { get; }
|
||||
```
|
||||
|
||||
## Thread Safety
|
||||
|
||||
The current implementation is **single-threaded**. For multi-threaded applications, external synchronization is required. A concurrent version is planned for future releases.
|
||||
|
||||
## Comparison with Other Allocators
|
||||
|
||||
### vs TLSF (Two-Level Segregated Fit)
|
||||
|
||||
| Aspect | HLSF | TLSF | Notes |
|
||||
|--------|------|------|-------|
|
||||
| Allocation Speed | ~2M ops/sec | ~3-5M ops/sec | HLSF has optimization potential |
|
||||
| Deallocation Speed | ~25M ops/sec | ~10-15M ops/sec | **HLSF advantage** |
|
||||
| Memory Overhead | ~2.8% | ~1-2% | HLSF uses external metadata |
|
||||
| Time Complexity | O(1) | O(1) | Equal |
|
||||
| Code Complexity | Moderate | Low | HLSF more sophisticated |
|
||||
|
||||
### Strengths
|
||||
- Superior deallocation performance
|
||||
- Clean separation of data and metadata
|
||||
- Configurable alignment support
|
||||
- Excellent for allocation-heavy workloads
|
||||
|
||||
### Areas for Improvement
|
||||
- Allocation speed optimization
|
||||
- Memory overhead reduction
|
||||
- Concurrent implementation
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
### Alignment Guarantees
|
||||
|
||||
- Minimum alignment: 16 bytes
|
||||
- All allocations respect specified alignment
|
||||
- Internal blocks aligned to 64-byte boundaries for optimal cache performance
|
||||
|
||||
### Merging Strategy
|
||||
|
||||
The allocator employs an aggressive merging strategy:
|
||||
|
||||
1. **Immediate Merging**: Adjacent free blocks are merged during deallocation
|
||||
2. **Boundary Checking**: Ensures merging respects level boundaries
|
||||
3. **Bidirectional Merging**: Checks both forward and backward neighbors
|
||||
4. **Level Promotion**: Merged blocks may be promoted to higher levels
|
||||
|
||||
## Future Roadmap
|
||||
|
||||
### Planned Optimizations
|
||||
|
||||
1. **Performance Enhancements**
|
||||
- Lookup table optimization for size classification
|
||||
- Bucket operation improvements
|
||||
- SIMD utilization for bulk operations
|
||||
|
||||
2. **Concurrent Support**
|
||||
- Thread-local caches
|
||||
- Lock-free bucket operations
|
||||
- NUMA-aware allocation
|
||||
|
||||
3. **Advanced Features**
|
||||
- Adaptive size level adjustment
|
||||
- Memory pressure handling
|
||||
- Statistics and profiling support
|
||||
|
||||
### Target Performance Goals
|
||||
|
||||
- Allocation Speed: 4-6M ops/sec (single-threaded)
|
||||
- Memory Overhead: <1.5%
|
||||
- Fragmentation Rate: <3%
|
||||
- Concurrent Scaling: Linear up to 16 threads
|
||||
|
||||
## Building and Testing
|
||||
|
||||
The HLSF allocator is part of the StgSharp.Common library and requires:
|
||||
|
||||
- .NET 8 or later
|
||||
- x64 architecture (no x86 support planned)
|
||||
- Windows/Linux
|
||||
|
||||
### Running Benchmarks
|
||||
|
||||
```csharp
|
||||
// See StgSharpDebug/Program.cs for comprehensive benchmark suite
|
||||
var allocator = new HybridLayerSegregatedFitAllocator(16 * 1024 * 1024);
|
||||
// Run allocation/deallocation cycles...
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This implementation is part of the StgSharp project and follows the project's licensing terms.
|
||||
|
||||
## Contributing
|
||||
|
||||
Performance improvements, bug fixes, and documentation enhancements are welcome. Please ensure all changes maintain the O(1) performance guarantees and include appropriate benchmarks.
|
||||
@@ -0,0 +1,153 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="SlabAllocator.ChunkedConcurrent.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
internal sealed unsafe class ConcurrentChunkedSlabAllocator<T> : SlabAllocator<T> where T: unmanaged
|
||||
{
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private ConcurrentBufferStack<nuint> _buffers;
|
||||
private ConcurrentBufferStack<nuint> _recycle;
|
||||
private readonly int _elementSize = Unsafe.SizeOf<T>();
|
||||
|
||||
private nuint _currentBuffer;
|
||||
private nuint _currentCapacity, _currentIndex;
|
||||
|
||||
public ConcurrentChunkedSlabAllocator(nuint count)
|
||||
{
|
||||
_currentBuffer = (nuint)NativeMemory.Alloc(count * (nuint)_elementSize);
|
||||
_currentCapacity = count;
|
||||
int initCount = count switch
|
||||
{
|
||||
<= 4 => 4,
|
||||
> 64 => 64,
|
||||
_ => (int)count
|
||||
};
|
||||
Span<nuint> span = stackalloc nuint[initCount];
|
||||
for (int i = 0; i < initCount; i++) {
|
||||
span[i] = _currentBuffer + (nuint)(i * _elementSize);
|
||||
}
|
||||
_buffers = new(4);
|
||||
_recycle = BufferStackBuilder.CreateConcurrent(span);
|
||||
_currentCapacity = count;
|
||||
_currentIndex = (nuint)initCount;
|
||||
}
|
||||
|
||||
public override nuint Allocate()
|
||||
{
|
||||
if (_recycle.TryPop(out nuint handle)) {
|
||||
return handle;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
nuint bufferHandle = Volatile.Read(ref _currentBuffer);
|
||||
nuint curIndex = Volatile.Read(ref _currentIndex);
|
||||
_lock.EnterMetaDataRead();
|
||||
try
|
||||
{
|
||||
if (curIndex >= _currentCapacity)
|
||||
{
|
||||
_lock.ExitMetaDataRead();
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
nuint cap = Volatile.Read(ref _currentCapacity);
|
||||
nuint newBuffer = (nuint)NativeMemory.Alloc(cap * (nuint)_elementSize);
|
||||
_buffers.Push(bufferHandle);
|
||||
_ = Interlocked.Exchange(ref _currentBuffer, newBuffer);
|
||||
_ = Interlocked.Exchange(ref _currentIndex, 0);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
}
|
||||
curIndex = Volatile.Read(ref _currentIndex);
|
||||
_ = Interlocked.Add(
|
||||
ref Unsafe.As<nuint, ulong>(ref _currentIndex), (ulong)_elementSize);
|
||||
return _currentBuffer + ((nuint)_elementSize * curIndex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsThreadReadingMetaData) {
|
||||
_lock.ExitMetaDataRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
NativeMemory.Free((void*)_currentBuffer);
|
||||
while (_buffers.TryPop(out nuint buffer)) {
|
||||
NativeMemory.Free((void*)buffer);
|
||||
}
|
||||
_lock.Dispose();
|
||||
_buffers.Dispose();
|
||||
_recycle.Dispose();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void EnterBufferReading() { }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void ExitBufferReading() { }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void Free(nuint index)
|
||||
{
|
||||
_recycle.Push(index);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override SlabAllocationHandle<T> ReadAllocation()
|
||||
{
|
||||
return new SlabAllocationHandle<T>(this, false);
|
||||
}
|
||||
|
||||
~ConcurrentChunkedSlabAllocator()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="SlabAllocator.SequencialConcurrent.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public sealed unsafe class ConcurrentSequentialSlabAllocator<T> : SlabAllocator<T> where T: unmanaged
|
||||
{
|
||||
|
||||
private T* _buffer;
|
||||
|
||||
private readonly BufferExpansionLock _lock = new();
|
||||
private readonly ConcurrentBufferStack<nuint> _stack;
|
||||
private readonly int _elementSize;
|
||||
private nuint _highestAllocated;
|
||||
private ulong _capacity;
|
||||
|
||||
public ConcurrentSequentialSlabAllocator(nuint initialCapacity)
|
||||
{
|
||||
_elementSize = Unsafe.SizeOf<T>();
|
||||
_capacity = initialCapacity;
|
||||
_highestAllocated = 0;
|
||||
|
||||
_buffer = (T*)NativeMemory.Alloc((nuint)_capacity * (nuint)_elementSize);
|
||||
int initCount = _capacity switch
|
||||
{
|
||||
<= 4 => 4,
|
||||
> 64 => 64,
|
||||
_ => (int)_capacity / 4
|
||||
};
|
||||
Span<nuint> span = stackalloc nuint[initCount];
|
||||
for (int i = 0; i < initCount; i++) {
|
||||
span[i] = (nuint)i;
|
||||
}
|
||||
_stack = BufferStackBuilder.CreateConcurrent(span);
|
||||
_highestAllocated += (nuint)initCount;
|
||||
}
|
||||
|
||||
internal T* BasePointer
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => _buffer;
|
||||
}
|
||||
|
||||
public override nuint Allocate()
|
||||
{
|
||||
if (_stack.TryPop(out nuint index)) {
|
||||
return index;
|
||||
}
|
||||
while (true)
|
||||
{
|
||||
index = Volatile.Read(ref _highestAllocated);
|
||||
_lock.EnterMetaDataRead();
|
||||
try
|
||||
{
|
||||
if (index >= _capacity)
|
||||
{
|
||||
_lock.ExitMetaDataRead();
|
||||
_lock.EnterExpansionProcess();
|
||||
try
|
||||
{
|
||||
_capacity = Volatile.Read(ref _capacity) * 2;
|
||||
nuint newSize = (nuint)_capacity * (nuint)_elementSize;
|
||||
_lock.EnterBufferCopy();
|
||||
try
|
||||
{
|
||||
_buffer = (T*)NativeMemory.Realloc(_buffer, newSize);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitBufferCopy();
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_lock.ExitExpansionProcess();
|
||||
}
|
||||
}
|
||||
_ = Interlocked.Increment(ref Unsafe.As<nuint, ulong>(ref _highestAllocated));
|
||||
return index;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_lock.IsThreadReadingMetaData) {
|
||||
_lock.ExitMetaDataRead();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
_stack.Dispose();
|
||||
NativeMemory.Free(_buffer);
|
||||
_lock.Dispose();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void EnterBufferReading()
|
||||
{
|
||||
_lock.EnterBufferRead();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override void ExitBufferReading()
|
||||
{
|
||||
_lock.ExitBufferRead();
|
||||
}
|
||||
|
||||
public override void Free(nuint index)
|
||||
{
|
||||
_stack.Push(index);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public override SlabAllocationHandle<T> ReadAllocation()
|
||||
{
|
||||
EnterBufferReading();
|
||||
return new SlabAllocationHandle<T>(this, true);
|
||||
}
|
||||
|
||||
~ConcurrentSequentialSlabAllocator()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryHandle.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public unsafe struct UnmanagedMemoryHandle
|
||||
{
|
||||
|
||||
public readonly byte* BufferHandle, AllocatorHandle;
|
||||
public readonly nuint Size;
|
||||
|
||||
public UnmanagedMemoryHandle(byte* pointer, byte* handle, nuint s)
|
||||
{
|
||||
BufferHandle = pointer;
|
||||
AllocatorHandle = handle;
|
||||
Size = s;
|
||||
}
|
||||
|
||||
public readonly ref byte this[nuint index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref Unsafe.AddByteOffset(ref Unsafe.AsRef<byte>(BufferHandle), index);
|
||||
}
|
||||
|
||||
public readonly Enumerator GetEnumerator()
|
||||
{
|
||||
return new Enumerator(this);
|
||||
}
|
||||
|
||||
public ref struct Enumerator : IEnumerator<byte>
|
||||
{
|
||||
|
||||
private nuint _index = nuint.MaxValue;
|
||||
|
||||
private UnmanagedMemoryHandle _handle;
|
||||
|
||||
internal Enumerator(UnmanagedMemoryHandle span)
|
||||
{
|
||||
_handle = span;
|
||||
}
|
||||
|
||||
public ref byte RefCurrent => ref _handle[_index];
|
||||
|
||||
public readonly void Dispose() { }
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
_index++;
|
||||
return _index < _handle.Size;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_index = 0;
|
||||
}
|
||||
|
||||
object IEnumerator.Current => RefCurrent;
|
||||
|
||||
byte IEnumerator<byte>.Current => RefCurrent;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.BucketTLSF.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance.Memory;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
private struct Entry : ISlabAllocatable
|
||||
{
|
||||
|
||||
public Entry* NextNear, PreviousNear;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Drawing;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Transactions;
|
||||
|
||||
namespace StgSharp.HighPerformance.Memory
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
private byte* m_Buffer;
|
||||
private SlabAllocator<Entry> _nodes = new(64);
|
||||
|
||||
public
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryHandle.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public ref struct UnmanagedMemoryHandle
|
||||
{
|
||||
|
||||
public nuint Postion;
|
||||
public Span<byte> Buffer;
|
||||
|
||||
public UnmanagedMemoryHandle() { }
|
||||
|
||||
public ref byte this[int index]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref Buffer[index];
|
||||
}
|
||||
|
||||
public Span<byte>.Enumerator GetEnumerator()
|
||||
{
|
||||
return Buffer.GetEnumerator();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.IndexNode.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
private const int
|
||||
LevelOf4096 = 4,
|
||||
LevelOf1024 = 3,
|
||||
LevelOf256 = 2,
|
||||
LevelOf64 = 1;
|
||||
|
||||
internal readonly ref struct NextIndexNode
|
||||
{
|
||||
|
||||
private readonly Span<M64> _layout;
|
||||
|
||||
public readonly nuint this[int level]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Position - _layout[level].Member<uint>(0);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => _layout[level].Member<uint>(0) = (uint)(Position - value);
|
||||
}
|
||||
|
||||
private readonly ref nuint Position
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref _layout[0].Member<nuint>(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal readonly ref struct PreviousIndexNode
|
||||
{
|
||||
|
||||
private readonly Span<M64> _layout;
|
||||
|
||||
public readonly nuint this[int level]
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => Position - _layout[level].Member<uint>(1);
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
set => _layout[level].Member<uint>(1) = (uint)(Position - value);
|
||||
}
|
||||
|
||||
private readonly ref nuint Position
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref _layout[0].Member<nuint>(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
internal readonly ref struct IndexNode
|
||||
{
|
||||
|
||||
private static readonly uint[] _sizeArr = [16, 64, 256, 1024, 4096];
|
||||
[FieldOffset(0)] private readonly NextIndexNode nxt;
|
||||
[FieldOffset(0)] private readonly PreviousIndexNode pre;
|
||||
[FieldOffset(0)] private readonly Span<M64> _layout;
|
||||
|
||||
public IndexNode(ref byte span)
|
||||
{
|
||||
_layout = MemoryMarshal.CreateSpan(ref Unsafe.As<byte, M64>(ref span), 8);
|
||||
}
|
||||
|
||||
public readonly ref nuint Position => ref _layout[0].Member<nuint>(0);
|
||||
|
||||
public readonly ref uint Size => ref _layout[5].Member<uint>(0);
|
||||
|
||||
public readonly ref int Level => ref _layout[5].Member<int>(1);
|
||||
|
||||
public readonly ref nuint Segment => ref _layout[6].Member<nuint>(0);
|
||||
|
||||
public readonly uint BlockSize => LevelToSize(Level);
|
||||
|
||||
public static uint LevelToSize(int level)
|
||||
{
|
||||
return level switch
|
||||
{
|
||||
< 0 or > 4 => throw new ArgumentOutOfRangeException(
|
||||
nameof(level), "Level must be from 1 to 4."),
|
||||
_ => _sizeArr[level]
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public readonly ref readonly NextIndexNode Next
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref nxt;
|
||||
}
|
||||
|
||||
public readonly ref readonly PreviousIndexNode Previous
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get => ref pre;
|
||||
}
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,187 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.IndexOperation.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private void ConnectToNodeAtLevel(
|
||||
IndexNode previous,
|
||||
IndexNode current,
|
||||
int level,
|
||||
bool isHead)
|
||||
{
|
||||
if (isHead)
|
||||
{
|
||||
_entrance[level] = current.Position;
|
||||
current.Previous[level] = 0;
|
||||
} else
|
||||
{
|
||||
previous.Next[level] = current.Previous[level] = (uint)(current.Position - previous.Position);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private IndexNode GetNode(nuint pos)
|
||||
{
|
||||
ref byte span = ref *(_buffer + pos);
|
||||
IndexNode node = new(ref span)
|
||||
{
|
||||
Position = pos
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private bool IsNodeBeginning(nuint pos, int level)
|
||||
{
|
||||
return _entrance[level] == pos;
|
||||
}
|
||||
|
||||
private bool Rebase(IndexNode n, uint offset)
|
||||
{
|
||||
nuint pos = n.Position;
|
||||
uint size = n.Size;
|
||||
if (size <= offset + 64)
|
||||
{
|
||||
for (int i = 0; i <= n.Level; i++) {
|
||||
RemoveLevelHead(n, i);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
uint
|
||||
newOffset = ((offset / 64) + 1) * 64,
|
||||
remain = n.Size - newOffset,
|
||||
c64 = remain % 4,
|
||||
c256 = remain / 4,
|
||||
c1024 = c256 / 4,
|
||||
c4096 = c1024 / 4;
|
||||
c256 %= 4;
|
||||
c1024 %= 4;
|
||||
IndexNode
|
||||
/*
|
||||
* level is not important here, higher level will get 0 Size,
|
||||
* and ignored in coming logic
|
||||
*/
|
||||
p64 = GetNode(n.Position - n.Previous[1]),
|
||||
p256 = GetNode(n.Position - n.Previous[2]),
|
||||
p1024 = GetNode(n.Position - n.Previous[3]),
|
||||
p4096 = GetNode(n.Position - n.Previous[4]),
|
||||
n64 = GetNode(n.Position + n.Previous[1]),
|
||||
n256 = GetNode(n.Position + n.Previous[2]),
|
||||
n1024 = GetNode(n.Position + n.Previous[3]),
|
||||
n4096 = GetNode(n.Position + n.Previous[4]);
|
||||
IndexNode nTemp;
|
||||
if (c64 != 0)
|
||||
{
|
||||
// set param to separated 64 bytes block and set next and previous offset to it.
|
||||
size = c64 * 64;
|
||||
pos += size;
|
||||
nTemp = GetNode(pos);
|
||||
nTemp.Position = pos;
|
||||
nTemp.Size = size;
|
||||
ConnectToNodeAtLevel(p64, nTemp, 1, n.Position == _entrance[1]);
|
||||
p64 = nTemp;
|
||||
}
|
||||
if (c256 != 0)
|
||||
{
|
||||
size = c256 * 256;
|
||||
pos += size;
|
||||
nTemp = GetNode(pos);
|
||||
nTemp.Position = pos;
|
||||
nTemp.Size = size;
|
||||
nTemp.Previous[2] = n.Previous[2] + size;
|
||||
ConnectToNodeAtLevel(p64, nTemp, 1, p64.Position == _entrance[1]);
|
||||
ConnectToNodeAtLevel(p256, nTemp, 2, n.Position == _entrance[2]);
|
||||
p64 = p256 = nTemp;
|
||||
}
|
||||
if (c1024 != 0)
|
||||
{
|
||||
size = c1024 * 1024;
|
||||
pos += size;
|
||||
nTemp = GetNode(pos);
|
||||
nTemp.Position = pos;
|
||||
nTemp.Size = size;
|
||||
nTemp.Previous[2] = n.Previous[2] + size;
|
||||
|
||||
// connect to previous node
|
||||
ConnectToNodeAtLevel(p64, nTemp, 1, p64.Position == _entrance[1]);
|
||||
ConnectToNodeAtLevel(p256, nTemp, 2, p256.Position == _entrance[2]);
|
||||
ConnectToNodeAtLevel(p1024, nTemp, 3, n.Position == _entrance[3]);
|
||||
p64 = p256 = p1024 = nTemp;
|
||||
}
|
||||
if (c4096 != 0)
|
||||
{
|
||||
size = c1024 * 1024;
|
||||
pos += size;
|
||||
nTemp = GetNode(pos);
|
||||
nTemp.Position = pos;
|
||||
nTemp.Size = size;
|
||||
nTemp.Previous[2] = n.Previous[2] + size;
|
||||
|
||||
// connect to previous node
|
||||
ConnectToNodeAtLevel(p64, nTemp, 1, p64.Position == _entrance[1]);
|
||||
ConnectToNodeAtLevel(p256, nTemp, 2, p256.Position == _entrance[2]);
|
||||
ConnectToNodeAtLevel(p1024, nTemp, 3, p1024.Position == _entrance[3]);
|
||||
ConnectToNodeAtLevel(p4096, nTemp, 4, n.Position == _entrance[4]);
|
||||
p64 = p256 = p1024 = p4096 = nTemp;
|
||||
}
|
||||
|
||||
ConnectToNodeAtLevel(p64, n64, 1, false);
|
||||
ConnectToNodeAtLevel(
|
||||
p256, n256, 2, _entrance[2] == n.Position && n256.Position == n.Position);
|
||||
ConnectToNodeAtLevel(
|
||||
p1024, n1024, 3, _entrance[3] == n.Position && n1024.Position == n.Position);
|
||||
ConnectToNodeAtLevel(
|
||||
p4096, n4096, 4, _entrance[4] == n.Position && n4096.Position == n.Position);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void RemoveLevelHead(IndexNode n, int level)
|
||||
{
|
||||
IndexNode nxt, pre;
|
||||
if (n.Previous[level] == 0)
|
||||
{
|
||||
// head of usable LEVEL;
|
||||
nxt = GetNode(n.Position + n.Next[level]);
|
||||
_entrance[level] = nxt.Position;
|
||||
}
|
||||
pre = GetNode(n.Previous[level]);
|
||||
nxt = GetNode(n.Next[level]);
|
||||
nxt.Previous[level] = nxt.Previous[level] + n.Previous[level];
|
||||
pre.Next[level] = pre.Next[level] + n.Next[level];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.MegaManage.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
private readonly LinkedList<MegaBlockHead> _megaAlloc = new();
|
||||
|
||||
private readonly LinkedList<MegaBlockHead> _megaEmpty = new();
|
||||
private MegaBlockHead _megaFirst;
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void InsertMegaNear(MegaBlockHead previous, MegaBlockHead current)
|
||||
{
|
||||
MegaBlockHead pp = current.PreviousNear;
|
||||
pp.NextNear = previous;
|
||||
previous.PreviousNear = pp;
|
||||
previous.NextNear = current;
|
||||
current.PreviousNear = previous;
|
||||
}
|
||||
|
||||
private static void InsertMegaSorted(LinkedList<MegaBlockHead> list, MegaBlockHead newItem)
|
||||
{
|
||||
LinkedListNode<MegaBlockHead>? node = list.First;
|
||||
|
||||
while (node != null && node.Value.Position < newItem.Position) {
|
||||
node = node.Next;
|
||||
}
|
||||
|
||||
_ = node != null ? list.AddBefore(node, newItem) : list.AddLast(newItem);
|
||||
}
|
||||
|
||||
private bool TryGetMegaBlock(nuint size, out nuint position, int align = 1)
|
||||
{
|
||||
LinkedListNode<MegaBlockHead> node = _megaEmpty.First!;
|
||||
while (node is not null)
|
||||
{
|
||||
MegaBlockHead block = node.Value;
|
||||
if (block.Size >= size + (nuint)align)
|
||||
{
|
||||
position = block.Position;
|
||||
nuint s = position + (nuint)(align - 1);
|
||||
MegaBlockHead b;
|
||||
if (block.Rebase(s))
|
||||
{
|
||||
b = new()
|
||||
{
|
||||
Position = position,
|
||||
Size = position + (nuint)(align - 1),
|
||||
Usage = MegaBlockUsage.MegaAlloc,
|
||||
};
|
||||
InsertMegaSorted(_megaAlloc, b);
|
||||
InsertMegaNear(b, block);
|
||||
} else
|
||||
{
|
||||
b = new()
|
||||
{
|
||||
Position = position,
|
||||
Size = block.Size,
|
||||
Usage = MegaBlockUsage.MegaAlloc,
|
||||
};
|
||||
InsertMegaSorted(_megaAlloc, b);
|
||||
_megaEmpty.Remove(node);
|
||||
InsertMegaNear(b, block.NextNear);
|
||||
}
|
||||
position = s & (nuint)~(align - 1);
|
||||
return true;
|
||||
}
|
||||
node = node.Next!;
|
||||
}
|
||||
position = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
private unsafe class MegaBlockHead
|
||||
{
|
||||
|
||||
private readonly ulong[] Heads = new ulong[4];
|
||||
|
||||
public MegaBlockHead NextNear { get; set; }
|
||||
|
||||
public MegaBlockHead PreviousNear { get; set; }
|
||||
|
||||
public MegaBlockUsage Usage { get; set; }
|
||||
|
||||
public nuint Position { get; set; }
|
||||
|
||||
public nuint Size { get; set; }
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public ref nuint DagHead(int level)
|
||||
{
|
||||
return ref Unsafe.As<ulong, nuint>(ref Heads[level]);
|
||||
}
|
||||
|
||||
public bool Rebase(nuint size)
|
||||
{
|
||||
nuint s = this.Size - size;
|
||||
if (s > 1024 * 1024 * 128)//space larger than 128MB is considered a new mega block
|
||||
{
|
||||
Position += size;
|
||||
this.Size -= size;
|
||||
Usage = MegaBlockUsage.EmptyDag;
|
||||
return true;
|
||||
}
|
||||
MegaBlockHead pre = PreviousNear, nxt = NextNear;
|
||||
pre.NextNear = nxt;
|
||||
nxt.PreviousNear = pre;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private enum MegaBlockUsage
|
||||
{
|
||||
|
||||
EmptyDag = 0,
|
||||
UsedDag = 1,
|
||||
MegaAlloc = 2
|
||||
|
||||
}
|
||||
|
||||
private MegaBlockHead
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
//-----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
// file="UnmanagedMemoryPool.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
// -----------------------------------------------------------------------
|
||||
// -----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Net.Security;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
using System.Transactions;
|
||||
|
||||
namespace StgSharp.HighPerformance
|
||||
{
|
||||
public unsafe partial class UnmanagedMemoryPool
|
||||
{
|
||||
|
||||
private readonly byte* _buffer;
|
||||
|
||||
// 4k,1k,256b,64b,16b
|
||||
private nuint[] _entrance = new nuint[5];
|
||||
private bool _disposedValue;
|
||||
private readonly nuint _initialCapacity;
|
||||
|
||||
internal UnmanagedMemoryPool(nuint initialCapacity, int memoryAlign)
|
||||
{
|
||||
_initialCapacity = initialCapacity;
|
||||
_buffer = (byte*)NativeMemory.AlignedAlloc(initialCapacity, (nuint)memoryAlign);
|
||||
}
|
||||
|
||||
public UnmanagedMemoryHandle Allocate(uint size = 0)
|
||||
{
|
||||
if (size == 0) {
|
||||
return new UnmanagedMemoryHandle
|
||||
{
|
||||
Postion = 0,
|
||||
Buffer = new Span<byte>(_buffer, 0)
|
||||
};
|
||||
}
|
||||
if (size > 0x8000_0000) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
"Size of buffer cannot be greater than 2147483648");
|
||||
}
|
||||
int level = GetLevelFromSize(size);
|
||||
IndexNode allocator = GetNode(_entrance[level]);
|
||||
nuint previous = allocator.Previous[level];
|
||||
if (allocator.Size < size)
|
||||
{
|
||||
previous = allocator.Position;
|
||||
allocator = GetNode(allocator.Next[level]);
|
||||
}
|
||||
bool isOverflow = false;
|
||||
checked
|
||||
{
|
||||
try
|
||||
{
|
||||
isOverflow = (uint)(allocator.Position - previous + size) > 0xC0000000;
|
||||
}
|
||||
catch (OverflowException)
|
||||
{
|
||||
isOverflow = true;
|
||||
}
|
||||
}
|
||||
if (isOverflow)
|
||||
{
|
||||
// offset is too large
|
||||
}
|
||||
|
||||
UnmanagedMemoryHandle handle = new()
|
||||
{
|
||||
Postion = allocator.Position,
|
||||
Buffer = new Span<byte>(_buffer + allocator.Position, (int)size),
|
||||
};
|
||||
Rebase(allocator, size);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public static UnmanagedMemoryPool Create(nuint initialCapacity, int memoryAlign = 16)
|
||||
{
|
||||
UnmanagedMemoryPool pool = new(initialCapacity, memoryAlign);
|
||||
IndexNode node = pool.GetNode(0);
|
||||
for (int i = 4; i > 0; i--)
|
||||
{
|
||||
node.Previous[i] = 0;
|
||||
node.Next[i] = IndexNode.LevelToSize(i);
|
||||
}
|
||||
node.Size = (uint)initialCapacity;
|
||||
pool._megaFirst = new MegaBlockHead
|
||||
{
|
||||
Position = 0,
|
||||
Size = initialCapacity,
|
||||
Usage = MegaBlockUsage.EmptyDag
|
||||
};
|
||||
_ = pool._megaEmpty.AddLast(pool._megaFirst);
|
||||
return pool;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(disposing:true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
public void Free(UnmanagedMemoryHandle handle)
|
||||
{
|
||||
if (_buffer + handle.Postion != Unsafe.AsPointer(ref handle.Buffer[0])) {
|
||||
throw new InvalidOperationException("Handle does not belong to pool");
|
||||
}
|
||||
nuint location = handle.Postion;
|
||||
IndexNode root = GetNode(_entrance[4]);
|
||||
while (root.Position > location) { }
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposedValue)
|
||||
{
|
||||
if (disposing) { }
|
||||
|
||||
NativeMemory.AlignedFree(_buffer);
|
||||
_entrance = null!;
|
||||
_disposedValue = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private int GetLevelFromSize(uint size)
|
||||
{
|
||||
int level = 0;
|
||||
uint temp = size / 8;
|
||||
while (temp > 3)
|
||||
{
|
||||
level++;
|
||||
temp >>= 2;
|
||||
}
|
||||
return level;
|
||||
}
|
||||
|
||||
~UnmanagedMemoryPool()
|
||||
{
|
||||
Dispose(disposing:false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="MatInterface.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Internal.Intrinsic
|
||||
{
|
||||
public interface IMat { }
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Blueprint.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
/// <summary>
|
||||
/// A sets of complex logic designed for running in multi threads environment. Warning: do not
|
||||
/// run a <see cref="BlueprintScheduler" /> instance in multi threads more than once.
|
||||
/// </summary>
|
||||
public partial class BlueprintScheduler : IConvertableToBlueprintNode
|
||||
{
|
||||
|
||||
private BeginningNode beginNode;
|
||||
private Dictionary<string, BlueprintNode> allNode;
|
||||
private EndingNode endNode;
|
||||
|
||||
private Func<bool> terminate;
|
||||
private List<BlueprintNode> globalNodeList;
|
||||
private List<BlueprintNode> nativeNodeList;
|
||||
|
||||
private SemaphoreSlim runningStat;
|
||||
|
||||
internal int currentGlobalNodeIndex;
|
||||
internal int currentNativeNodeIndex;
|
||||
|
||||
public BlueprintScheduler()
|
||||
{
|
||||
allNode = new Dictionary<string, BlueprintNode>();
|
||||
globalNodeList = new List<BlueprintNode>();
|
||||
nativeNodeList = new List<BlueprintNode>();
|
||||
runningStat = new SemaphoreSlim( 1, 1 );
|
||||
beginNode = new BeginningNode( this );
|
||||
endNode = new EndingNode( this );
|
||||
}
|
||||
|
||||
public BlueprintNode BeginLayer => beginNode;
|
||||
|
||||
public BlueprintNode EndLayer => endNode;
|
||||
|
||||
public BlueprintNodeOperation Operation
|
||||
{
|
||||
get => ExecuteMain;
|
||||
}
|
||||
|
||||
public bool IsRunning
|
||||
{
|
||||
get => runningStat.CurrentCount == 0;
|
||||
}
|
||||
|
||||
public IEnumerable<string> InputInterfacesName
|
||||
{
|
||||
get { return beginNode.OutputInterfaces.Keys; }
|
||||
}
|
||||
|
||||
public IEnumerable<string> OutputInterfacesName
|
||||
{
|
||||
get { return beginNode.OutputInterfaces.Keys; }
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
internal SemaphoreSlim RunningStat
|
||||
{
|
||||
get => runningStat;
|
||||
}
|
||||
/**/
|
||||
|
||||
public void AddNode( BlueprintNode node, bool isNative )
|
||||
{
|
||||
_ = node ?? throw new ArgumentNullException( nameof( node ) );
|
||||
node.IsNative = isNative;
|
||||
allNode.Add( node.Name, node );
|
||||
}
|
||||
|
||||
public void ExecuteMain(
|
||||
in Dictionary<string, BlueprintPipeline> input,
|
||||
in Dictionary<string, BlueprintPipeline> output )
|
||||
{
|
||||
BlueprintRunner.Run( this );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public (string name, BlueprintPipelineArgs arg)[] GetOutput()
|
||||
{
|
||||
return endNode.OutputData;
|
||||
}
|
||||
|
||||
public void Init()
|
||||
{
|
||||
foreach( KeyValuePair<string, BlueprintNode> item in allNode ) {
|
||||
if( item.Value.IsNative ) {
|
||||
nativeNodeList.Add( item.Value );
|
||||
} else {
|
||||
globalNodeList.Add( item.Value );
|
||||
}
|
||||
}
|
||||
nativeNodeList.Sort();
|
||||
globalNodeList.Sort();
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public void SetInput(
|
||||
params (string name, BlueprintPipelineArgs arg)[] parameters )
|
||||
{
|
||||
beginNode.InputData = parameters;
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
Interlocked.Exchange( ref currentGlobalNodeIndex, int.MaxValue );
|
||||
Interlocked.Exchange( ref currentNativeNodeIndex, int.MaxValue );
|
||||
}
|
||||
|
||||
internal bool RequestNexGlobalNode( out BlueprintNode node )
|
||||
{
|
||||
if( currentGlobalNodeIndex < globalNodeList.Count ) {
|
||||
node = globalNodeList[ currentGlobalNodeIndex ];
|
||||
Interlocked.Increment( ref currentGlobalNodeIndex );
|
||||
return true;
|
||||
}
|
||||
node = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
internal bool RequestNextNativeNode( out BlueprintNode node )
|
||||
{
|
||||
if( currentNativeNodeIndex < nativeNodeList.Count ) {
|
||||
node = nativeNodeList[ currentNativeNodeIndex ];
|
||||
Interlocked.Increment( ref currentNativeNodeIndex );
|
||||
return true;
|
||||
}
|
||||
node = default!;
|
||||
return false;
|
||||
}
|
||||
|
||||
~BlueprintScheduler()
|
||||
{
|
||||
runningStat.Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="BlueprintNode.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Entities;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <risk>
|
||||
/// Reset pipeline has risk, this operation is a direct operation to port in current node, the
|
||||
/// port on the other node cannot get the change.
|
||||
/// </risk>
|
||||
#pragma warning disable CA1036
|
||||
public class BlueprintNode : IComparable<BlueprintNode>
|
||||
#pragma warning restore CA1036
|
||||
{
|
||||
|
||||
private static BlueprintNode _emptyNode = new BlueprintNode(
|
||||
string.Empty, null!, false );
|
||||
|
||||
private static Dictionary<string, BlueprintPipeline> _emptyLayer = new();
|
||||
private protected bool _levelAvailable, _nativeRequested;
|
||||
private protected Dictionary<string, BlueprintPipeline> _inputInterfaces;
|
||||
private protected Dictionary<string, BlueprintPipeline> _outputInterfaces;
|
||||
private protected int _level;
|
||||
private IConvertableToBlueprintNode _mainOperation;
|
||||
private string _name;
|
||||
|
||||
internal BlueprintNode(
|
||||
string name,
|
||||
IConvertableToBlueprintNode node,
|
||||
bool isNative )
|
||||
{
|
||||
_levelAvailable = false;
|
||||
_name = name;
|
||||
_nativeRequested = isNative;
|
||||
_mainOperation = node;
|
||||
_inputInterfaces = new Dictionary<string, BlueprintPipeline>();
|
||||
_outputInterfaces = new Dictionary<string, BlueprintPipeline>();
|
||||
foreach( string portName in node.InputInterfacesName ) {
|
||||
_inputInterfaces.Add( portName, null! );
|
||||
}
|
||||
|
||||
foreach( string portName in node.OutputInterfacesName ) {
|
||||
_outputInterfaces.Add( portName, null! );
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning disable CS8618
|
||||
internal BlueprintNode(
|
||||
BlueprintNodeOperation operation,
|
||||
string name,
|
||||
bool isNative,
|
||||
string[] inputPorts,
|
||||
string[] outputPorts )
|
||||
#pragma warning restore CS8618
|
||||
{
|
||||
if( ( inputPorts == null ) || ( inputPorts.Length == 0 ) ) {
|
||||
throw new ArgumentNullException( nameof( inputPorts ) );
|
||||
}
|
||||
if( ( outputPorts == null ) || ( outputPorts.Length == 0 ) ) {
|
||||
throw new ArgumentNullException( nameof( outputPorts ) );
|
||||
}
|
||||
_levelAvailable = false;
|
||||
_name = name;
|
||||
_nativeRequested = isNative;
|
||||
operation = operation ?? DefaultOperation;
|
||||
_mainOperation = new DefaultConvertableToBlueprintNode(
|
||||
operation,
|
||||
inputPorts,
|
||||
outputPorts);
|
||||
_inputInterfaces = new Dictionary<string, BlueprintPipeline>();
|
||||
_outputInterfaces = new Dictionary<string, BlueprintPipeline>();
|
||||
foreach( string portName in inputPorts ) {
|
||||
_inputInterfaces.Add(
|
||||
portName,
|
||||
SealedBlueprintPiipeline.SealOutput( this, name ) );
|
||||
}
|
||||
foreach( string portName in outputPorts ) {
|
||||
_outputInterfaces.Add( portName, null! );
|
||||
}
|
||||
}
|
||||
|
||||
protected static void DefaultOperation(
|
||||
in Dictionary<string, BlueprintPipeline> input,
|
||||
in Dictionary<string, BlueprintPipeline> output)
|
||||
{
|
||||
BlueprintPipeline.SkipAll(output);
|
||||
}
|
||||
|
||||
public static BlueprintNode Empty
|
||||
{
|
||||
get => _emptyNode;
|
||||
}
|
||||
|
||||
public bool IsNative
|
||||
{
|
||||
get => _nativeRequested;
|
||||
internal set => _nativeRequested = value;
|
||||
}
|
||||
|
||||
public static Dictionary<string, BlueprintPipeline> EmptyPortLayer
|
||||
{
|
||||
get => _emptyLayer;
|
||||
}
|
||||
|
||||
public int Level
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _levelAvailable ) {
|
||||
return _level;
|
||||
}
|
||||
_level = 0;
|
||||
foreach( KeyValuePair<string, BlueprintPipeline> item in _inputInterfaces ) {
|
||||
if( item.Value == null ) {
|
||||
continue;
|
||||
}
|
||||
if( _level < item.Value.Level ) {
|
||||
_level = item.Value.Level;
|
||||
}
|
||||
}
|
||||
_level += 1;
|
||||
_levelAvailable = true;
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
|
||||
public string Name => _name;
|
||||
|
||||
internal Dictionary<string, BlueprintPipeline> InputInterfaces => _inputInterfaces;
|
||||
|
||||
internal Dictionary<string, BlueprintPipeline> OutputInterfaces => _outputInterfaces;
|
||||
|
||||
internal IConvertableToBlueprintNode Value
|
||||
{
|
||||
get => _mainOperation;
|
||||
}
|
||||
|
||||
public void Append(
|
||||
[NotNull] BlueprintNode next,
|
||||
string thisOutputPortName,
|
||||
string afterInputPortName )
|
||||
{
|
||||
this._levelAvailable = false;
|
||||
BlueprintPipeline pipeline = new BlueprintPipeline( this, next );
|
||||
if( next is EndingNode enode ) {
|
||||
enode.SetCertainInputPort( afterInputPortName, pipeline );
|
||||
} else {
|
||||
next.SetCertainInputPort( afterInputPortName, pipeline );
|
||||
}
|
||||
SetCertainOutputPort( thisOutputPortName, pipeline );
|
||||
}
|
||||
|
||||
public int CompareTo( BlueprintNode other )
|
||||
{
|
||||
if( null == other ) {
|
||||
throw new ArgumentNullException( nameof( other ) );
|
||||
}
|
||||
|
||||
return this.Level.CompareTo( other.Level );
|
||||
}
|
||||
|
||||
public void Prepend(
|
||||
[NotNull] BlueprintNode former,
|
||||
string formerOutputPortName,
|
||||
string thisInputPortName )
|
||||
{
|
||||
this._levelAvailable = false;
|
||||
BlueprintPipeline pipeline = new BlueprintPipeline( former, this );
|
||||
if( former is BeginningNode bnode ) {
|
||||
bnode.SetCertainOutputPort( formerOutputPortName, pipeline );
|
||||
} else {
|
||||
former.SetCertainOutputPort( formerOutputPortName, pipeline );
|
||||
}
|
||||
SetCertainInputPort( thisInputPortName, pipeline );
|
||||
}
|
||||
|
||||
public virtual void Run()
|
||||
{
|
||||
try {
|
||||
//Console.WriteLine(_name);
|
||||
BlueprintPipeline.WaitAll( _inputInterfaces );
|
||||
if( _mainOperation != null ) {
|
||||
_mainOperation.Operation(
|
||||
in _inputInterfaces, in _outputInterfaces );
|
||||
}
|
||||
}
|
||||
catch( Exception ) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#region port operation
|
||||
|
||||
public BlueprintPipeline GetInputPort( string name )
|
||||
{
|
||||
BlueprintPipeline ret;
|
||||
if( !_inputInterfaces.TryGetValue( name, out ret ) ) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"Cannot find the interface named {name} in node {Name}." );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public BlueprintPipeline GetOutputPort( string name )
|
||||
{
|
||||
BlueprintPipeline ret;
|
||||
if( !_outputInterfaces.TryGetValue( name, out ret ) ) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"Cannot find the interface named {name} in node {Name}." );
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void SetCertainInputPort(
|
||||
string name,
|
||||
BlueprintPipeline pipeline )
|
||||
{
|
||||
if( !_inputInterfaces.ContainsKey( name ) ) {
|
||||
throw new ArgumentException(
|
||||
$"Cannot find the interface named {name} in node {Name}." );
|
||||
}
|
||||
_inputInterfaces[ name ] = pipeline;
|
||||
}
|
||||
|
||||
public void SetCertainOutputPort(
|
||||
string name,
|
||||
BlueprintPipeline pipeline )
|
||||
{
|
||||
if( !_outputInterfaces.ContainsKey( name ) ) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
$"Cannot find the interface named {name} in node {Name}." );
|
||||
}
|
||||
_outputInterfaces[ name ] = pipeline;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}//--------------------------------- end of class -----------------------------------
|
||||
|
||||
public class BlueprintNodeRunException : Exception
|
||||
{
|
||||
|
||||
protected BlueprintNodeRunException(
|
||||
SerializationInfo info,
|
||||
StreamingContext context )
|
||||
: base( info, context ) { }
|
||||
|
||||
public BlueprintNodeRunException() { }
|
||||
|
||||
public BlueprintNodeRunException( Exception ex )
|
||||
: base( string.Empty, ex ) { }
|
||||
|
||||
public BlueprintNodeRunException( string message ) : base( message ) { }
|
||||
|
||||
public BlueprintNodeRunException(
|
||||
string message,
|
||||
Exception innerException )
|
||||
: base( message, innerException ) { }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="BlueprintNodeCraeater.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public partial class BlueprintScheduler
|
||||
{
|
||||
|
||||
public BlueprintNode CreateBlueprintNode(
|
||||
string name,
|
||||
BlueprintNodeOperation operation,
|
||||
string[] inputPort,
|
||||
string[] outputPort,
|
||||
bool isNative )
|
||||
{
|
||||
BlueprintNode node = new BlueprintNode(
|
||||
operation, name, isNative, inputPort, outputPort );
|
||||
if( isNative ) {
|
||||
nativeNodeList.Add( node );
|
||||
} else {
|
||||
globalNodeList.Add( node );
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,229 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="BlueprintRunner.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Threading;
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public static class BlueprintRunner
|
||||
{
|
||||
|
||||
private static NodeRunner[] allAvailableTask = CreateBlueprintRunnerArray(
|
||||
);
|
||||
private static CancellationTokenSource cts = new CancellationTokenSource(
|
||||
);
|
||||
private static ConcurrentStack<BlueprintScheduler> blueprintInWaiting
|
||||
= new ConcurrentStack<BlueprintScheduler>();
|
||||
private static int _callingThread;
|
||||
private static SemaphoreSlim bpLock = new SemaphoreSlim( 0, 1 );
|
||||
|
||||
/// <summary>
|
||||
/// Only the fallowing occasions of calling are valid: 1. no bp is running or the only bp is
|
||||
/// quitting. 2. calling from the main thread and the current running bp.
|
||||
/// </summary>
|
||||
internal static bool IsValidCalling
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( NodeRunner.CurrentBlueprint == null ) || //no bp running at all
|
||||
( ( blueprintInWaiting.IsEmpty ) && ( NodeRunner.CurrentBlueprint.IsRunning ==
|
||||
false ) ) )
|
||||
// a bp is quiting
|
||||
{
|
||||
//in case no bp is running
|
||||
return true;
|
||||
}
|
||||
int? id = Task.CurrentId;
|
||||
if( id is null ) {
|
||||
// in case calling from main thread and current running bp
|
||||
return _callingThread == Environment.CurrentManagedThreadId;
|
||||
}
|
||||
foreach( NodeRunner item in allAvailableTask ) {
|
||||
if( item.Id == id ) {
|
||||
//if calling from any bp running task
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Run( BlueprintScheduler blueprint )
|
||||
{
|
||||
//Console.WriteLine();
|
||||
if( blueprint == null ) {
|
||||
return;
|
||||
}
|
||||
if( blueprint.IsRunning ) {
|
||||
throw new InvalidOperationException(
|
||||
"Attempt to run a blueprint instance twice." );
|
||||
}
|
||||
if( IsValidCalling ) {
|
||||
//Console.WriteLine("valid and run");
|
||||
if( InterruptAndRunNewBp( blueprint ) ) {
|
||||
while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { }
|
||||
;
|
||||
}
|
||||
} else {
|
||||
bpLock.Wait();
|
||||
if( InterruptAndRunNewBp( blueprint ) ) {
|
||||
while( InterruptAndRunNewBp( NodeRunner.CurrentBlueprint ) ) { }
|
||||
}
|
||||
|
||||
bpLock.Release();
|
||||
}
|
||||
Interlocked.Exchange( ref _callingThread, -1 );
|
||||
}
|
||||
|
||||
public static void SetMaxTaskCount( int size )
|
||||
{
|
||||
if( size < 1 ) {
|
||||
size = 1;
|
||||
}
|
||||
if( allAvailableTask.Length >= size ) {
|
||||
for( int i = size; i < allAvailableTask.Length; i++ ) {
|
||||
if( allAvailableTask[ i ] != null ) {
|
||||
allAvailableTask[ i ].Cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
Array.Resize( ref allAvailableTask, size );
|
||||
}
|
||||
|
||||
public static void Terminate()
|
||||
{
|
||||
cts.Cancel();
|
||||
NodeRunner.CurrentBlueprint.Terminate();
|
||||
foreach( NodeRunner task in allAvailableTask ) {
|
||||
task.Cts.Cancel();
|
||||
}
|
||||
foreach( BlueprintScheduler bp in blueprintInWaiting ) {
|
||||
bp.Terminate();
|
||||
}
|
||||
blueprintInWaiting.Clear();
|
||||
}
|
||||
|
||||
internal static bool InterruptAndRunNewBp( BlueprintScheduler newBp )
|
||||
{
|
||||
Debug.Assert( newBp != null );
|
||||
if( ( newBp != NodeRunner.CurrentBlueprint ) && ( NodeRunner.CurrentBlueprint !=
|
||||
null ) ) {
|
||||
//if a running bp exists
|
||||
blueprintInWaiting.Push( NodeRunner.CurrentBlueprint );
|
||||
}
|
||||
|
||||
//load new bp to current bp
|
||||
Interlocked.Exchange( ref NodeRunner.CurrentBlueprint!, newBp );
|
||||
Interlocked.Exchange(
|
||||
ref _callingThread, Environment.CurrentManagedThreadId );
|
||||
|
||||
//run beginning node to init it first.
|
||||
if( !NodeRunner.CurrentBlueprint.IsRunning ) {
|
||||
( NodeRunner.CurrentBlueprint.BeginLayer as BeginningNode )!.Run(
|
||||
);
|
||||
}
|
||||
|
||||
//refresh all tasks
|
||||
for( int i = 0; i < allAvailableTask.Length; i++ ) {
|
||||
NodeRunner item = allAvailableTask[ i ];
|
||||
if( ( item is null ) || item.IsCompleted ) {
|
||||
allAvailableTask[ i ] = NodeRunner.Run();
|
||||
}
|
||||
}
|
||||
BlueprintNode node;
|
||||
while( !cts.Token.IsCancellationRequested && NodeRunner.CurrentBlueprint
|
||||
.RequestNextNativeNode( out node ) ) {
|
||||
node.Run();
|
||||
if( !NodeRunner.CurrentBlueprint.IsRunning ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
( NodeRunner.CurrentBlueprint.EndLayer as EndingNode )!.Run();
|
||||
return blueprintInWaiting.TryPeek( out NodeRunner.CurrentBlueprint );
|
||||
}
|
||||
|
||||
private static NodeRunner[] CreateBlueprintRunnerArray()
|
||||
{
|
||||
int count = Environment.ProcessorCount;
|
||||
return new NodeRunner[ count < 2 ? count : count - 2];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class NodeRunner : CancellableTask
|
||||
{
|
||||
|
||||
private static BlueprintScheduler _current;
|
||||
|
||||
internal NodeRunner()
|
||||
: base()
|
||||
{
|
||||
_startup = InternalRun;
|
||||
}
|
||||
|
||||
internal static ref BlueprintScheduler CurrentBlueprint
|
||||
{
|
||||
get => ref _current;
|
||||
}
|
||||
|
||||
internal static NodeRunner Run()
|
||||
{
|
||||
NodeRunner ret = new NodeRunner { _startup = InternalRun };
|
||||
ret._internalTask = Task.Run( ret.InternalAction );
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static void InternalRun( CancellationToken token )
|
||||
{
|
||||
//Console.WriteLine("Task Begin");
|
||||
BlueprintNode item;
|
||||
while( ( CurrentBlueprint != null ) && CurrentBlueprint.IsRunning && !token.IsCancellationRequested && CurrentBlueprint.RequestNexGlobalNode(
|
||||
out item ) ) {
|
||||
//Console.WriteLine($"Get node of {item.Name}, going to run.");
|
||||
item.Run();
|
||||
}
|
||||
|
||||
//Console.WriteLine("Task Completed");
|
||||
}
|
||||
|
||||
}//------------------------------------- End of Class ------------------------------------------
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="CrossFrameBlueprintNode.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Blueprint;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public class CrossFrameOperation : IConvertableToBlueprintNode
|
||||
{
|
||||
|
||||
private static string[] _inputName = ["TaskIn"];
|
||||
private static string[] _outputName = ["TaskOut"];
|
||||
private Action _mainExecution;
|
||||
private int currentCount;
|
||||
private readonly int cycleCount;
|
||||
|
||||
public CrossFrameOperation( Action startup, int cycleCount )
|
||||
{
|
||||
MainExecution = startup;
|
||||
this.cycleCount = ( cycleCount > 1 ) ?
|
||||
cycleCount : throw new ArgumentException(
|
||||
$"{$"The {typeof(CrossFrameOperation).Name} crosses only one cycle, "}{$"please use a {typeof(BlueprintNode).Name} instead."}" );
|
||||
this.cycleCount = cycleCount;
|
||||
currentCount = cycleCount;
|
||||
}
|
||||
|
||||
public Action MainExecution
|
||||
{
|
||||
get => _mainExecution;
|
||||
private protected set => _mainExecution = value;
|
||||
}
|
||||
|
||||
public BlueprintNodeOperation Operation
|
||||
{
|
||||
get => ExecuteMain;
|
||||
}
|
||||
|
||||
public IEnumerable<string> InputInterfacesName => _inputName;
|
||||
|
||||
public IEnumerable<string> OutputInterfacesName => _outputName;
|
||||
|
||||
public void ExecuteMain(
|
||||
in Dictionary<string, BlueprintPipeline> input,
|
||||
in Dictionary<string, BlueprintPipeline> output )
|
||||
{
|
||||
if( currentCount < cycleCount ) {
|
||||
Interlocked.Increment( ref currentCount );
|
||||
} else {
|
||||
Interlocked.Exchange( ref currentCount, 0 );
|
||||
Task.Run( MainExecution );
|
||||
}
|
||||
|
||||
//Console.WriteLine(currentCount);
|
||||
BlueprintPipeline.SkipAll( output );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IConvertableToBlueprintNode.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public delegate void BlueprintNodeOperation(
|
||||
in Dictionary<string, BlueprintPipeline> input,
|
||||
in Dictionary<string, BlueprintPipeline> output );
|
||||
|
||||
public interface IConvertableToBlueprintNode
|
||||
{
|
||||
|
||||
BlueprintNodeOperation Operation
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public IEnumerable<string> InputInterfacesName
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public IEnumerable<string> OutputInterfacesName
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class DefaultConvertableToBlueprintNode : IConvertableToBlueprintNode
|
||||
{
|
||||
|
||||
private string[] _input;
|
||||
private string[] _output;
|
||||
private BlueprintNodeOperation _execution;
|
||||
|
||||
public DefaultConvertableToBlueprintNode(
|
||||
BlueprintNodeOperation execution,
|
||||
string[] input,
|
||||
string[] output )
|
||||
{
|
||||
_input = input;
|
||||
_output = output;
|
||||
_execution = execution;
|
||||
}
|
||||
|
||||
public BlueprintNodeOperation Operation => _execution;
|
||||
|
||||
public IEnumerable<string> InputInterfacesName => _input;
|
||||
|
||||
public IEnumerable<string> OutputInterfacesName => _output;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="PipeLine.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Authentication.ExtendedProtection;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public class BlueprintPipeline
|
||||
{
|
||||
|
||||
private protected BlueprintNode after;
|
||||
private protected BlueprintNode former;
|
||||
private protected BlueprintPipelineArgs args;
|
||||
private protected SemaphoreSlim formerCompleteSemaphore;
|
||||
|
||||
public BlueprintPipeline( BlueprintNode former, BlueprintNode after )
|
||||
{
|
||||
this.former = former;
|
||||
this.after = after;
|
||||
formerCompleteSemaphore = new SemaphoreSlim(
|
||||
initialCount: 0, maxCount: 1 );
|
||||
}
|
||||
|
||||
public BlueprintNode After => after;
|
||||
|
||||
public BlueprintNode Former => former;
|
||||
|
||||
public BlueprintPipelineArgs Args
|
||||
{
|
||||
get => args;
|
||||
set => args = value;
|
||||
}
|
||||
|
||||
public int Level => former.Level;
|
||||
|
||||
public static void SkipAll(
|
||||
Dictionary<string, BlueprintPipeline> ports )
|
||||
{
|
||||
if( ports == null ) {
|
||||
return;
|
||||
}
|
||||
foreach( KeyValuePair<string, BlueprintPipeline> item in ports ) {
|
||||
if( item.Value != null ) {
|
||||
item.Value.CompleteAndSkip();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WaitAll(
|
||||
Dictionary<string, BlueprintPipeline> ports )
|
||||
{
|
||||
if( ports == null ) {
|
||||
return;
|
||||
}
|
||||
foreach( KeyValuePair<string, BlueprintPipeline> item in ports ) {
|
||||
if( item.Value != null ) {
|
||||
item.Value.WaitForStart();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void WaitForStart()
|
||||
{
|
||||
//Console.WriteLine($"Waiting \t{former.ContextName}\t->\t{after.ContextName}");
|
||||
formerCompleteSemaphore.Wait();
|
||||
}
|
||||
|
||||
~BlueprintPipeline()
|
||||
{
|
||||
formerCompleteSemaphore.Dispose();
|
||||
}
|
||||
|
||||
#region pipline op
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public void CompleteAndSkip()
|
||||
{
|
||||
//Console.WriteLine($"Complete\t{former.Name}\t->\t{after.Name}");
|
||||
formerCompleteSemaphore.Release();
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public void CompleteAndWriteData( BlueprintPipelineArgs args )
|
||||
{
|
||||
this.args = args;
|
||||
CompleteAndSkip();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
public abstract class BlueprintPipelineArgs
|
||||
{
|
||||
public object? Value
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
public object? ValueDefault
|
||||
{
|
||||
get;
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class SealedBlueprintPiipeline:BlueprintPipeline
|
||||
{
|
||||
internal SealedBlueprintPiipeline(BlueprintNode former, BlueprintNode after):
|
||||
base(former, after)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public static SealedBlueprintPiipeline SealOutput(BlueprintNode node, string portName)
|
||||
{
|
||||
return new SealedBlueprintPiipeline(node, BlueprintNode.Empty);
|
||||
}
|
||||
|
||||
public static SealedBlueprintPiipeline SealInput(BlueprintNode node, string portName)
|
||||
{
|
||||
return new SealedBlueprintPiipeline(BlueprintNode.Empty, node);
|
||||
}
|
||||
|
||||
public sealed override void WaitForStart()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="RouteSwitch.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
public class RouteSwitch : BlueprintNode
|
||||
{
|
||||
|
||||
private protected Dictionary<string, (BlueprintPipeline pipeline, Func<bool> openingRule)> outputDictionary;
|
||||
|
||||
public RouteSwitch( string name, bool isNative, string inputPorts )
|
||||
: base(DefaultOperation, name, isNative, [inputPorts], [string.Empty] )
|
||||
{
|
||||
outputDictionary = new Dictionary<string, (BlueprintPipeline pipeline, Func<bool> openingRule)>(
|
||||
);
|
||||
}
|
||||
|
||||
public new int Level
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _levelAvailable ) {
|
||||
return _level;
|
||||
}
|
||||
_level = 0;
|
||||
KeyValuePair<string, BlueprintPipeline> item = _inputInterfaces.First(
|
||||
);
|
||||
if( item.Value == null ) {
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
if( _level <= item.Value.Level ) {
|
||||
_level = item.Value.Level;
|
||||
}
|
||||
return _level;
|
||||
}
|
||||
}
|
||||
|
||||
public new void AddBefore(
|
||||
BlueprintNode after,
|
||||
string thisOutputPortName,
|
||||
string afterInputPortName )
|
||||
{
|
||||
this.AppendNode( after, afterInputPortName, () => true );
|
||||
}
|
||||
|
||||
public void AppendNode(
|
||||
BlueprintNode node,
|
||||
string portName,
|
||||
Func<bool> openningRule )
|
||||
{
|
||||
if( node == null ) {
|
||||
throw new ArgumentNullException( nameof( node ) );
|
||||
}
|
||||
string indexName = $"{node.Name}.{portName}";
|
||||
BlueprintPipeline p = new BlueprintPipeline( this, node );
|
||||
node.InputInterfaces[ portName ] = p;
|
||||
outputDictionary.Add( indexName, (p, openningRule) );
|
||||
}
|
||||
|
||||
public new void Run()
|
||||
{
|
||||
try {
|
||||
BlueprintPipeline input = InputInterfaces.First().Value;
|
||||
input.WaitForStart();
|
||||
foreach( KeyValuePair<string, (BlueprintPipeline pipeline, Func<bool> openingRule)> item in outputDictionary ) {
|
||||
if( item.Value.openingRule() ) {
|
||||
item.Value.pipeline.CompleteAndWriteData( input.Args );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch( Exception ) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="SideNode.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Blueprint
|
||||
{
|
||||
internal sealed class BeginningNode : BlueprintNode
|
||||
{
|
||||
|
||||
private BlueprintScheduler _bp;
|
||||
|
||||
public BeginningNode( BlueprintScheduler bp )
|
||||
: base(
|
||||
DefaultOperation, name: "BeginningNode", true, ["default"],
|
||||
["default"] )
|
||||
{
|
||||
_bp = bp;
|
||||
}
|
||||
|
||||
internal (string name, BlueprintPipelineArgs arg)[] InputData
|
||||
{
|
||||
set
|
||||
{
|
||||
if( value == null ) {
|
||||
return;
|
||||
}
|
||||
foreach( (string name, BlueprintPipelineArgs arg) parameter in value ) {
|
||||
OutputInterfaces[ parameter.name ].Args = parameter.arg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
_bp.RunningStat.Wait();
|
||||
BlueprintPipeline.SkipAll( _outputInterfaces );
|
||||
}
|
||||
|
||||
public new void SetCertainOutputPort(
|
||||
string name,
|
||||
BlueprintPipeline pipeline )
|
||||
{
|
||||
if( _outputInterfaces.ContainsKey( name ) ) {
|
||||
_outputInterfaces[ name ] = pipeline;
|
||||
}
|
||||
_outputInterfaces.Add( name, pipeline );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal sealed class EndingNode : BlueprintNode
|
||||
{
|
||||
|
||||
private BlueprintScheduler _bp;
|
||||
|
||||
public EndingNode( BlueprintScheduler bp )
|
||||
: base(
|
||||
DefaultOperation, name: "EndingNode", true, ["default"],
|
||||
["default"] )
|
||||
{
|
||||
_bp = bp;
|
||||
}
|
||||
|
||||
internal (string name, BlueprintPipelineArgs arg)[] OutputData
|
||||
{
|
||||
get { return InputInterfaces.Select(
|
||||
key => (key.Key, key.Value.Args) )
|
||||
.ToArray(); }
|
||||
}
|
||||
|
||||
public override void Run()
|
||||
{
|
||||
BlueprintPipeline.WaitAll( _inputInterfaces );
|
||||
Interlocked.Exchange( ref _bp.currentGlobalNodeIndex, 0 );
|
||||
Interlocked.Exchange( ref _bp.currentNativeNodeIndex, 0 );
|
||||
_bp.RunningStat.Release();
|
||||
}
|
||||
|
||||
public new void SetCertainInputPort(
|
||||
string name,
|
||||
BlueprintPipeline pipeline )
|
||||
{
|
||||
if( _inputInterfaces.ContainsKey( name ) ) {
|
||||
_inputInterfaces[ name ] = pipeline;
|
||||
}
|
||||
_inputInterfaces.Add( name, pipeline );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Counter.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace StgSharp
|
||||
{
|
||||
public class Counter<T>
|
||||
where T: struct, IConvertible, IFormattable, IComparable
|
||||
#if NET8_OR_GREATER
|
||||
,INumber
|
||||
#endif
|
||||
{
|
||||
internal dynamic _value;
|
||||
|
||||
internal readonly T _defualtIncreament;
|
||||
internal readonly T _defualtDecreament;
|
||||
internal readonly T _defaultValue;
|
||||
|
||||
public Counter( T defualtValue, T defualtIncreament, T defualtDecreament )
|
||||
{
|
||||
Type tType = typeof( T );
|
||||
if (
|
||||
tType != typeof(byte) &&
|
||||
tType != typeof(short) &&
|
||||
tType != typeof(int) &&
|
||||
tType != typeof(long) &&
|
||||
tType != typeof(sbyte) &&
|
||||
tType != typeof(ushort) &&
|
||||
tType != typeof(uint) &&
|
||||
tType != typeof(ulong) &&
|
||||
tType != typeof(float) &&
|
||||
tType != typeof(double))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Input is not number value type");
|
||||
}
|
||||
|
||||
_value = defualtValue;
|
||||
_defaultValue = defualtValue;
|
||||
_defualtIncreament = defualtIncreament;
|
||||
_defualtDecreament = defualtDecreament;
|
||||
}
|
||||
|
||||
public T DecreamentSoan => _defualtDecreament;
|
||||
|
||||
public T IncreamentSpan => _defualtIncreament;
|
||||
|
||||
public T CurrentSpan => _value - _defaultValue;
|
||||
|
||||
public T Value
|
||||
{
|
||||
get => _value;
|
||||
set => _value = value;
|
||||
}
|
||||
|
||||
public void Add( T value )
|
||||
{
|
||||
_value += value;
|
||||
}
|
||||
|
||||
public void QuickAdd()
|
||||
{
|
||||
_value += _defualtIncreament;
|
||||
}
|
||||
|
||||
public void QuickSub()
|
||||
{
|
||||
_value -= _defualtDecreament;
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_value = _defaultValue;
|
||||
}
|
||||
|
||||
public void Sub( T value )
|
||||
{
|
||||
_value -= value;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Value.ToString();
|
||||
}
|
||||
|
||||
public static Counter<T> operator --( Counter<T> counter )
|
||||
{
|
||||
counter.QuickSub();
|
||||
return counter;
|
||||
}
|
||||
|
||||
public static Counter<T> operator ++( Counter<T> counter )
|
||||
{
|
||||
counter.QuickAdd();
|
||||
return counter;
|
||||
}
|
||||
|
||||
public static implicit operator T( Counter<T> counter )
|
||||
{
|
||||
return counter.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="PlainGeometryCollisionSensor.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Geometries;
|
||||
|
||||
using System;
|
||||
|
||||
namespace StgSharp
|
||||
{
|
||||
public class CollisionEventArgs:EventArgs
|
||||
{
|
||||
public CollisionEventArgs(IGeometry target, IGeometry boarder)
|
||||
{
|
||||
Target = target;
|
||||
Boarder = boarder;
|
||||
}
|
||||
|
||||
public IGeometry Target { get; set; }
|
||||
public IGeometry Boarder { get; set; }
|
||||
}
|
||||
|
||||
public class PlainGeometryCollisionSensor<TBoarder,TTarget>
|
||||
where TBoarder : IGeometry
|
||||
where TTarget : IGeometry
|
||||
{
|
||||
internal PlainGeometry _boarder;
|
||||
internal PlainGeometry _target;
|
||||
internal EventHandler<CollisionEventArgs> _rule;
|
||||
|
||||
public event EventHandler<CollisionEventArgs> Rule
|
||||
{
|
||||
add { _rule += value; }
|
||||
remove
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#pragma warning disable CS8601
|
||||
_rule -= value;
|
||||
#pragma warning restore CS8601
|
||||
}
|
||||
}
|
||||
|
||||
public PlainGeometry boarder => _boarder;
|
||||
|
||||
public PlainGeometry target
|
||||
{
|
||||
get => _target;
|
||||
set => _target = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="StateMachine.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp
|
||||
{
|
||||
public interface IStateMachine<T> where T: Enum
|
||||
{
|
||||
|
||||
public T LastStableState
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public bool TryEnterState();
|
||||
|
||||
public bool TryExitState();
|
||||
|
||||
public bool TrySwitchState();
|
||||
|
||||
}
|
||||
|
||||
public interface IStateMachineWithSwitchSpan<TState, TSpan> : IStateMachine<TState>
|
||||
where TState: Enum
|
||||
{
|
||||
|
||||
public bool IsInStabelState
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public TState NextStableState
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
public bool TrySwitchState();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="TimeFunction.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Timing
|
||||
{
|
||||
public class TimeFunction
|
||||
{
|
||||
|
||||
private float _beginning, _ending;
|
||||
private Func<float, float> _timeRelatedCalculation;
|
||||
private TimeSpanProvider _timeProvider;
|
||||
|
||||
internal TimeFunction() { }
|
||||
|
||||
public TimeFunction(
|
||||
TimeSpanProvider timeSpanProvider,
|
||||
Func<float, float> timeRelatedCalculation,
|
||||
float range )
|
||||
{
|
||||
_timeProvider = timeSpanProvider;
|
||||
_timeRelatedCalculation = timeRelatedCalculation;
|
||||
if( timeSpanProvider == null ) {
|
||||
return;
|
||||
}
|
||||
_beginning = _timeProvider.CurrentSecond;
|
||||
_ending = _timeProvider.CurrentSecond + range;
|
||||
}
|
||||
|
||||
public virtual bool IsComplete
|
||||
{
|
||||
get => _timeProvider.CurrentSecond > _ending;
|
||||
}
|
||||
|
||||
public Func<float, float> TimeRelatedCalculation
|
||||
{
|
||||
get { return _timeRelatedCalculation; }
|
||||
set { _timeRelatedCalculation = value; }
|
||||
}
|
||||
|
||||
public static TimeFunction One
|
||||
{
|
||||
get => new TimeFunctionOne();
|
||||
}
|
||||
|
||||
public TimeSpanProvider TimeSpanProvider
|
||||
{
|
||||
get { return _timeProvider; }
|
||||
set { _timeProvider = value; }
|
||||
}
|
||||
|
||||
public virtual float Calculate()
|
||||
{
|
||||
if( _timeProvider.CurrentSecond < _ending ) {
|
||||
return 0;
|
||||
}
|
||||
return _timeRelatedCalculation(
|
||||
_timeProvider.CurrentSecond - _beginning );
|
||||
}
|
||||
|
||||
public static TimeFunction Proportional(
|
||||
TimeSpanProvider time,
|
||||
float begin,
|
||||
float range )
|
||||
{
|
||||
return new TimeFunction( time, ( float t ) => t + begin, range );
|
||||
}
|
||||
|
||||
public virtual TimeFunction Renew(
|
||||
(Func<float, float> func, float range) funcPair )
|
||||
{
|
||||
return new TimeFunction(
|
||||
_timeProvider, funcPair.func, funcPair.range );
|
||||
}
|
||||
|
||||
public virtual TimeFunction Renew(
|
||||
Func<float, float> func,
|
||||
float range )
|
||||
{
|
||||
return new TimeFunction( _timeProvider, func, range );
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
float range = _ending - _beginning;
|
||||
_beginning = _timeProvider.CurrentSecond;
|
||||
_ending = _beginning + range;
|
||||
}
|
||||
|
||||
public virtual TimeFunction Reverse()
|
||||
{
|
||||
float range = _ending - _beginning;
|
||||
return new TimeFunction(
|
||||
_timeProvider, p => _timeRelatedCalculation( range - p ),
|
||||
range );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public sealed class TimeFunctionOne : TimeFunction
|
||||
{
|
||||
|
||||
internal TimeFunctionOne() : base() { }
|
||||
|
||||
public override bool IsComplete
|
||||
{
|
||||
get => true;
|
||||
}
|
||||
|
||||
public override float Calculate()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override TimeFunction Renew(
|
||||
(Func<float, float> func, float range) funcPair )
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public override TimeFunction Renew(
|
||||
Func<float, float> func,
|
||||
float range )
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#pragma warning disable CA1822
|
||||
public new void Reset()
|
||||
#pragma warning restore CA1822
|
||||
{ }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="TimeProvider.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using StgSharp.Timing;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp
|
||||
{
|
||||
public static partial class StgSharp
|
||||
{
|
||||
|
||||
internal static StgSharpTime mainTimeProvider = new StgSharpTime();
|
||||
|
||||
internal static TimeSourceProviderBase MainTimeProvider => mainTimeProvider;
|
||||
|
||||
}
|
||||
|
||||
public sealed class StgSharpTime : TimeSourceProviderBase
|
||||
{
|
||||
|
||||
private static List<TimeSpanProvider> subscriberList = new List<TimeSpanProvider>(
|
||||
);
|
||||
private static long accuracy;
|
||||
private static Stopwatch mainProvider = new Stopwatch();
|
||||
private static Thread timeProvideThread;
|
||||
|
||||
internal StgSharpTime() { }
|
||||
|
||||
public static TimeSourceProviderBase OnlyInstance => StgSharp.MainTimeProvider;
|
||||
|
||||
public override sealed void StartProvidingTime()
|
||||
{
|
||||
if( mainProvider.IsRunning ) {
|
||||
return;
|
||||
}
|
||||
mainProvider.Start();
|
||||
|
||||
//speed test
|
||||
long totalMS, internalFrequncy = Stopwatch.Frequency;
|
||||
for( int i = 0; i < 100; i++ ) {
|
||||
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) );
|
||||
for( int t = 0; t < 10; t++ ) {
|
||||
if( totalMS < 1000 ) {
|
||||
subscriberList.Add(
|
||||
new TimeSpanProvider(
|
||||
100L, TimeSpanProvider.DefaultProvider ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
mainProvider.Stop();
|
||||
subscriberList.Clear();
|
||||
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) ) / 100L;
|
||||
accuracy = ( totalMS * 2 ) / 3;
|
||||
mainProvider.Reset();
|
||||
timeProvideThread = new Thread( new ThreadStart( ProvideTime ) );
|
||||
timeProvideThread.Start();
|
||||
}
|
||||
|
||||
public override void StopProvidingTime()
|
||||
{
|
||||
lock( mainProvider ) {
|
||||
mainProvider.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
public void Terminate()
|
||||
{
|
||||
lock( mainProvider ) {
|
||||
mainProvider.Stop();
|
||||
}
|
||||
}
|
||||
|
||||
protected override sealed void AddSubscriberUnsynced(
|
||||
TimeSpanProvider subscriber )
|
||||
{
|
||||
subscriberList.Add( subscriber );
|
||||
}
|
||||
|
||||
protected override sealed void RemoveSubscriberUnsynced(
|
||||
TimeSpanProvider subscriber )
|
||||
{
|
||||
subscriberList.Remove( subscriber );
|
||||
}
|
||||
|
||||
private void ProvideTime()
|
||||
{
|
||||
long totalMS, internalFrequncy = Stopwatch.Frequency;
|
||||
lock( mainProvider ) {
|
||||
mainProvider.Restart();
|
||||
}
|
||||
while( mainProvider.IsRunning ) {
|
||||
totalMS = mainProvider.ElapsedTicks / ( internalFrequncy / ( 1000L * 1000L ) );
|
||||
if( subscriberList.Count == 0 ) {
|
||||
continue;
|
||||
}
|
||||
CheckSubscriberSemaphore.Wait();
|
||||
List<TimeSpanProvider> toRemoveList = new List<TimeSpanProvider>(
|
||||
);
|
||||
foreach( TimeSpanProvider subscriber in subscriberList ) {
|
||||
if( !subscriber.CheckTime( totalMS ) ) {
|
||||
toRemoveList.Add( subscriber );
|
||||
InternalIO.InternalWriteLog(
|
||||
$"Time subscriber {subscriber} is to be removed.",
|
||||
LogType.Info );
|
||||
}
|
||||
;
|
||||
}
|
||||
if( toRemoveList.Count != 0 ) {
|
||||
foreach( TimeSpanProvider subscriber in toRemoveList ) {
|
||||
subscriberList.Remove( subscriber );
|
||||
}
|
||||
}
|
||||
CheckSubscriberSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="TimeSourceProvider.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp;
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.Timing
|
||||
{
|
||||
public abstract class TimeSourceProviderBase
|
||||
{
|
||||
|
||||
private SemaphoreSlim _addSubscriberSemaphore = new SemaphoreSlim(
|
||||
1, 1 );
|
||||
|
||||
protected SemaphoreSlim CheckSubscriberSemaphore
|
||||
{
|
||||
get => _addSubscriberSemaphore;
|
||||
}
|
||||
|
||||
public void AddSubscriber( TimeSpanProvider subscriber )
|
||||
{
|
||||
try {
|
||||
_addSubscriberSemaphore.Wait();
|
||||
AddSubscriberUnsynced( subscriber );
|
||||
}
|
||||
catch( Exception ) {
|
||||
throw;
|
||||
}
|
||||
finally {
|
||||
_addSubscriberSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveSubscriber( TimeSpanProvider subscriber )
|
||||
{
|
||||
_addSubscriberSemaphore.Wait();
|
||||
try {
|
||||
RemoveSubscriberUnsynced( subscriber );
|
||||
}
|
||||
catch( Exception ) {
|
||||
throw;
|
||||
}
|
||||
finally {
|
||||
_addSubscriberSemaphore.Release();
|
||||
}
|
||||
}
|
||||
|
||||
public abstract void StartProvidingTime();
|
||||
|
||||
public abstract void StopProvidingTime();
|
||||
|
||||
protected abstract void AddSubscriberUnsynced(
|
||||
TimeSpanProvider subscriber );
|
||||
|
||||
protected abstract void RemoveSubscriberUnsynced(
|
||||
TimeSpanProvider subscriber );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="TimeSpanAwaitingToken.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Timing
|
||||
{
|
||||
#nullable enable
|
||||
|
||||
public sealed class TimeSpanAwaitingToken : IDisposable
|
||||
{
|
||||
|
||||
private static readonly ConcurrentStack<int> s_unusedID = new ConcurrentStack<int>(
|
||||
[0] );
|
||||
private static int s_maxID;
|
||||
private static readonly object s_lock = new object();
|
||||
|
||||
private EventHandler? _refreshHandler,_missHandler;
|
||||
private int _size, _id;
|
||||
|
||||
private object _participantObject = new object();
|
||||
private SemaphoreSlim _awaitingSemaphore;
|
||||
|
||||
private TimeSpanProvider _provider;
|
||||
|
||||
internal TimeSpanAwaitingToken( TimeSpanProvider provider )
|
||||
{
|
||||
if( s_unusedID.Count == 1 ) {
|
||||
lock( s_lock ) {
|
||||
s_unusedID.TryPop( out int id );
|
||||
TokenID = id;
|
||||
s_unusedID.Push( s_maxID++ );
|
||||
}
|
||||
} else {
|
||||
s_unusedID.TryPop( out int id );
|
||||
TokenID = id;
|
||||
}
|
||||
_provider = provider;
|
||||
_size = 1;
|
||||
_awaitingSemaphore = new SemaphoreSlim( 0, 1 );
|
||||
}
|
||||
|
||||
internal TimeSpanAwaitingToken( TimeSpanProvider provider, int count )
|
||||
{
|
||||
if( s_unusedID.Count == 1 ) {
|
||||
lock( s_lock ) {
|
||||
s_unusedID.TryPop( out int id );
|
||||
TokenID = id;
|
||||
s_unusedID.Push( s_maxID++ );
|
||||
}
|
||||
} else {
|
||||
s_unusedID.TryPop( out int id );
|
||||
TokenID = id;
|
||||
}
|
||||
_provider = provider;
|
||||
_size = count;
|
||||
_awaitingSemaphore = new SemaphoreSlim( 0, _size );
|
||||
}
|
||||
|
||||
public event EventHandler MissTimeSpanRefreshed
|
||||
{
|
||||
add { _missHandler += value; }
|
||||
remove { _missHandler -= value; }
|
||||
}
|
||||
|
||||
public event EventHandler TimeSpanRefreshed
|
||||
{
|
||||
add { _refreshHandler += value; }
|
||||
remove { _refreshHandler -= value; }
|
||||
}
|
||||
|
||||
public int TokenID
|
||||
{
|
||||
get => _id;
|
||||
private set => _id = value;
|
||||
}
|
||||
|
||||
internal SemaphoreSlim AwaitingSemaphoreSlim
|
||||
{
|
||||
get => _awaitingSemaphore;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_provider.QuitSpanAwaiting( this );
|
||||
s_unusedID.Push( TokenID );
|
||||
_awaitingSemaphore.Dispose();
|
||||
GC.SuppressFinalize( this );
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
|
||||
public void Participant()
|
||||
{
|
||||
lock( _participantObject ) {
|
||||
_size++;
|
||||
SemaphoreSlim newSemaphore = new SemaphoreSlim(
|
||||
_awaitingSemaphore.CurrentCount, _size );
|
||||
Interlocked.Exchange( ref _awaitingSemaphore, newSemaphore )
|
||||
.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
public void WaitNextSpan()
|
||||
{
|
||||
_awaitingSemaphore.Wait();
|
||||
}
|
||||
|
||||
internal void MissRefresh()
|
||||
{
|
||||
_missHandler?.Invoke( this, EventArgs.Empty );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal void Refresh()
|
||||
{
|
||||
_refreshHandler?.Invoke( this, EventArgs.Empty );
|
||||
}
|
||||
|
||||
~TimeSpanAwaitingToken()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
}
|
||||
#nullable restore
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="TimeSpanProvider.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
namespace StgSharp.Timing
|
||||
{
|
||||
/// <summary>
|
||||
/// A microsecond-accuracy timer. It will refresh every a certain time span.
|
||||
/// </summary>
|
||||
public class TimeSpanProvider
|
||||
{
|
||||
|
||||
private bool _subscribed;
|
||||
|
||||
private ConcurrentQueue<TimeSpanAwaitingToken> _tokenToAdd = new ConcurrentQueue<TimeSpanAwaitingToken>(
|
||||
);
|
||||
private ConcurrentQueue<TimeSpanAwaitingToken> _tokenToQuit;
|
||||
private Counter<int> timeSpanCount = new Counter<int>( -1, 1, 1 );
|
||||
private HashSet<TimeSpanAwaitingToken> _awaitingTokens;
|
||||
private long _maxSpanCount;
|
||||
private long _spanBegin;
|
||||
private readonly long _spanLength;
|
||||
private readonly TimeSourceProviderBase _timeSource;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
|
||||
/// of a single time span is defined in microseconds.
|
||||
/// </summary>
|
||||
/// <param _name="spanMicroSeconds"></param>
|
||||
/// <param _name="provider"></param>
|
||||
public TimeSpanProvider(
|
||||
long spanMicroSeconds,
|
||||
TimeSourceProviderBase provider )
|
||||
{
|
||||
if( provider == null ) {
|
||||
throw new ArgumentNullException( nameof( provider ) );
|
||||
}
|
||||
_timeSource = provider;
|
||||
_spanLength = spanMicroSeconds;
|
||||
_maxSpanCount = int.MaxValue;
|
||||
provider.AddSubscriber( this );
|
||||
_subscribed = true;
|
||||
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
|
||||
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
|
||||
/// of a single time span is defined in seconds.
|
||||
/// </summary>
|
||||
/// <param _name="spanSeconds"></param>
|
||||
/// <param _name="provider"></param>
|
||||
public TimeSpanProvider(
|
||||
double spanSeconds,
|
||||
TimeSourceProviderBase provider )
|
||||
{
|
||||
if( provider == null ) {
|
||||
throw new ArgumentNullException( nameof( provider ) );
|
||||
}
|
||||
_timeSource = provider;
|
||||
_spanLength = ( long )( spanSeconds * 1000L * 1000L );
|
||||
_spanBegin = -_spanLength;
|
||||
_maxSpanCount = long.MaxValue;
|
||||
provider.AddSubscriber( this );
|
||||
_subscribed = true;
|
||||
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
|
||||
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new <see cref="TimeSpanProvider" /> and define the length of time span. Length
|
||||
/// of a single time span is defined in microseconds.
|
||||
/// </summary>
|
||||
/// <param _name="spanLength"></param>
|
||||
/// <param _name="maxSpan"></param>
|
||||
/// <param _name="provider"></param>
|
||||
public TimeSpanProvider(
|
||||
long spanLength,
|
||||
long maxSpan,
|
||||
TimeSourceProviderBase provider )
|
||||
{
|
||||
if( provider == null ) {
|
||||
throw new ArgumentNullException( nameof( provider ) );
|
||||
}
|
||||
if( maxSpan <= 0 ) {
|
||||
throw new ArgumentException(
|
||||
"Sapn count cannot be smaller than zero" );
|
||||
}
|
||||
_timeSource = provider;
|
||||
_spanLength = spanLength;
|
||||
_spanBegin = -_spanLength;
|
||||
provider.AddSubscriber( this );
|
||||
_subscribed = true;
|
||||
_awaitingTokens = new HashSet<TimeSpanAwaitingToken>();
|
||||
_tokenToQuit = new ConcurrentQueue<TimeSpanAwaitingToken>();
|
||||
}
|
||||
|
||||
public double SpanLength
|
||||
{
|
||||
get => ( _spanLength * 1.0 ) / ( 1000L * 1000L );
|
||||
}
|
||||
|
||||
public float CurrentSecond
|
||||
{
|
||||
get => timeSpanCount.Value * SpanLengthLowPrecession;
|
||||
}
|
||||
|
||||
public float SpanLengthLowPrecession
|
||||
{
|
||||
get => ( _spanLength * 1.0f ) / ( 1000 * 1000 );
|
||||
}
|
||||
|
||||
public int CurrentSpan
|
||||
{
|
||||
get => timeSpanCount.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Time source provider provided in <see cref="StgSharp" /> internal framework.
|
||||
/// </summary>
|
||||
public static TimeSourceProviderBase DefaultProvider => StgSharpTime.OnlyInstance;
|
||||
|
||||
public TimeSpanAwaitingToken ParticipantSpanAwaiting( int count )
|
||||
{
|
||||
TimeSpanAwaitingToken token = new TimeSpanAwaitingToken(
|
||||
this, count );
|
||||
_tokenToAdd.Enqueue( token );
|
||||
return token;
|
||||
}
|
||||
|
||||
public void QuitSpanAwaiting( TimeSpanAwaitingToken token )
|
||||
{
|
||||
_tokenToQuit.Enqueue( token );
|
||||
}
|
||||
|
||||
public void StopSpanProviding()
|
||||
{
|
||||
Interlocked.Exchange( ref _maxSpanCount, 0 );
|
||||
}
|
||||
|
||||
public void SubscribeToTimeSource(
|
||||
TimeSourceProviderBase serviceHandler )
|
||||
{
|
||||
if( serviceHandler == null ) {
|
||||
throw new ArgumentNullException( nameof( serviceHandler ) );
|
||||
}
|
||||
if( _subscribed ) {
|
||||
return;
|
||||
}
|
||||
_subscribed = true;
|
||||
serviceHandler.AddSubscriber( this );
|
||||
}
|
||||
|
||||
public int ToInt32()
|
||||
{
|
||||
return timeSpanCount.Value;
|
||||
}
|
||||
|
||||
internal bool CheckTime( long microseconds )
|
||||
{
|
||||
if( microseconds - _spanBegin < _spanLength ) {
|
||||
return true;
|
||||
}
|
||||
while( !_tokenToAdd.IsEmpty ) {
|
||||
_tokenToAdd.TryDequeue( out TimeSpanAwaitingToken tokenAdd );
|
||||
_awaitingTokens.Add( tokenAdd );
|
||||
}
|
||||
while( !_tokenToQuit.IsEmpty ) {
|
||||
_tokenToQuit.TryDequeue( out TimeSpanAwaitingToken tokenQuit );
|
||||
_awaitingTokens.Remove( tokenQuit );
|
||||
InternalIO.InternalWriteLog(
|
||||
$"Awaiting token {tokenQuit!.TokenID} has been removed.",
|
||||
LogType.Info );
|
||||
}
|
||||
|
||||
_spanBegin = microseconds;
|
||||
timeSpanCount++;
|
||||
|
||||
foreach( TimeSpanAwaitingToken item in _awaitingTokens ) {
|
||||
if( item.AwaitingSemaphoreSlim.CurrentCount == 0 ) {
|
||||
item.AwaitingSemaphoreSlim.Release();
|
||||
item.Refresh();
|
||||
} else {
|
||||
item.MissRefresh();
|
||||
}
|
||||
}
|
||||
|
||||
return timeSpanCount < _maxSpanCount;
|
||||
}
|
||||
|
||||
public static explicit operator int(
|
||||
[NotNull]TimeSpanProvider provider )
|
||||
{
|
||||
return provider.ToInt32();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,313 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Camera.cs"
|
||||
// Project: StepVisualizer
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Graphics;
|
||||
using StgSharp.Graphics.OpenGL;
|
||||
using StgSharp.Graphics.ShaderEdit;
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Graphics
|
||||
{
|
||||
public sealed class Camera : IglConvertable
|
||||
{
|
||||
|
||||
private bool _isLookAtAvailable;
|
||||
internal Matrix44 _lookAt;
|
||||
internal Matrix44 _projection;
|
||||
internal Matrix44 cameraAtt;
|
||||
internal Matrix44 rotation;
|
||||
internal Matrix44 rotationAtt;
|
||||
internal Radius _pitch;
|
||||
internal Radius _row;
|
||||
internal Radius _yaw;
|
||||
internal Uniform<Matrix44> convertedUniform;
|
||||
internal Vec3 _target, up;
|
||||
|
||||
public Camera()
|
||||
{
|
||||
cameraAtt = Matrix44.Unit;
|
||||
_target = Vec3.Zero;
|
||||
up = Vec3.Zero;
|
||||
_isLookAtAvailable = false;
|
||||
_lookAt = Matrix44.Unit;
|
||||
rotationAtt = Matrix44.Unit;
|
||||
_projection = new Matrix44();
|
||||
}
|
||||
|
||||
public Camera( Vec3 position, Vec3 target, Vec3 up )
|
||||
: this()
|
||||
{
|
||||
rotationAtt = Matrix44.Unit;
|
||||
cameraAtt = new Matrix44();
|
||||
SetViewDirection( position, target, up );
|
||||
_pitch = Radius.Zero;
|
||||
_row = Radius.Zero;
|
||||
_yaw = Radius.Zero;
|
||||
}
|
||||
|
||||
public Matrix44 Projection => _projection;
|
||||
|
||||
public Matrix44 View
|
||||
{
|
||||
get
|
||||
{
|
||||
if( _isLookAtAvailable ) {
|
||||
return _lookAt;
|
||||
}
|
||||
Matrix44 move = Matrix44.Unit;
|
||||
move.colum3.vec -= cameraAtt.colum3.vec;
|
||||
_lookAt = rotationAtt.Transpose * move;
|
||||
_isLookAtAvailable = true;
|
||||
return _lookAt;
|
||||
}
|
||||
}
|
||||
|
||||
public Matrix44 CameraMatrix()
|
||||
{
|
||||
return Projection * View;
|
||||
}
|
||||
|
||||
public void DisplayGLtypeDefinition()
|
||||
{
|
||||
Console.WriteLine( "uniform matrix4x4 cameraName;" );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all uniform related to this <see cref="Camera" />.
|
||||
/// </summary>
|
||||
/// <param _label="source">
|
||||
/// Shader program requires this camera.
|
||||
/// </param>
|
||||
/// <param _label="uniformName">
|
||||
/// ContextName of all related uniforms. If you fallow form from <see
|
||||
/// cref="IglConvertable.DisplayGLtypeDefinition" />
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentException">
|
||||
///
|
||||
/// </exception>
|
||||
public unsafe void GainAllUniforms( ShaderProgram source, params string[] uniformName )
|
||||
{
|
||||
if( uniformName is null || uniformName.Length != 1 ) {
|
||||
throw new ArgumentException(
|
||||
"Camera needs exactly one uniform.", nameof( uniformName ) );
|
||||
}
|
||||
convertedUniform = source.GetUniform<Matrix44>( uniformName[ 0 ] );
|
||||
}
|
||||
|
||||
public void MoveNear( float distance )
|
||||
{
|
||||
cameraAtt.colum3.Z -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
public void MoveRight( float distance )
|
||||
{
|
||||
cameraAtt.colum3.X -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
public void MoveUp( float distance )
|
||||
{
|
||||
cameraAtt.colum3.Y -= distance;
|
||||
_isLookAtAvailable = false;
|
||||
}
|
||||
|
||||
public unsafe void SetAllUniforms()
|
||||
{
|
||||
//Console.WriteLine(Projection * ViewBase);
|
||||
OpenGL.OpenGLFunction.CurrentGL.SetUniformValue( convertedUniform, Projection * View );
|
||||
}
|
||||
|
||||
public void SetViewDirection( Vec3 position, Vec3 target, Vec3 up )
|
||||
{
|
||||
Vec3 direction = position - target;
|
||||
if( ( position.reg == cameraAtt.colum3.reg ) &&
|
||||
( this.up == up ) &&
|
||||
( cameraAtt.colum2.reg == direction.reg ) ) {
|
||||
return;
|
||||
}
|
||||
if( direction.GetLength() == 0 )
|
||||
{
|
||||
//deadlock
|
||||
throw new ArgumentException();
|
||||
}
|
||||
if( Vec3.IsParallel( direction, up ) ) {
|
||||
throw new ArgumentException();
|
||||
}
|
||||
_target = direction;
|
||||
this.up = up;
|
||||
|
||||
_isLookAtAvailable = false;
|
||||
|
||||
Linear.Orthogonalize( ref direction, ref up );
|
||||
|
||||
Vec3 right = Linear.Orthogonalize( Linear.Cross( up, direction ) );
|
||||
|
||||
cameraAtt.colum0.reg = right.reg;
|
||||
cameraAtt.colum1.reg = up.reg;
|
||||
cameraAtt.colum2.reg = direction.reg;
|
||||
cameraAtt.colum3.reg = position.reg;
|
||||
|
||||
InternalPitch();
|
||||
InternalRow();
|
||||
InternalYaw();
|
||||
}
|
||||
|
||||
public void SetViewRange(
|
||||
Radius fovRadius,
|
||||
Vec2 size,
|
||||
Vec2 offset,
|
||||
(float front, float back) dephRange )
|
||||
{
|
||||
float
|
||||
distance = _target.GetLength(),
|
||||
near = distance - dephRange.front,
|
||||
far = distance + dephRange.back,
|
||||
offsetX = offset.X,
|
||||
offsetY = offset.Y,
|
||||
width = Scaler.Abs( GeometryScaler.Tan( fovRadius / 2 ) * near * 2 ),
|
||||
height = ( width * size.Y ) / size.X;
|
||||
|
||||
_projection.colum0.X = ( 2 * near ) / width;
|
||||
_projection.colum1.Y = ( 2 * near ) / height;
|
||||
_projection.colum2.X = ( 2 * offsetX ) / width;
|
||||
_projection.colum2.Y = ( 2 * offsetY ) / height;
|
||||
_projection.colum2.Z = ( far + near ) / ( near - far );
|
||||
_projection.colum2.W = -1;
|
||||
_projection.colum3.Z = ( 2 * near * far ) / ( near - far );
|
||||
}
|
||||
|
||||
public void Test( params Vec4[] vec )
|
||||
{
|
||||
Console.WriteLine( View );
|
||||
Console.WriteLine( Projection );
|
||||
Console.WriteLine( Projection * View );
|
||||
Console.WriteLine( View );
|
||||
foreach( Vec4 item in vec ) {
|
||||
Console.Write( $"{Projection * View * item};" );
|
||||
}
|
||||
}
|
||||
|
||||
ShaderStruct IglConvertable.GetConvertedGLtype()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
~Camera() { }
|
||||
|
||||
#region rotation
|
||||
|
||||
public void Yaw( Radius r )
|
||||
{
|
||||
_yaw -= r;
|
||||
|
||||
//Console.WriteLine(_yaw._radius);
|
||||
//Console.WriteLine(rotationAtt);
|
||||
InternalYaw();
|
||||
}
|
||||
|
||||
public void Pitch( Radius r )
|
||||
{
|
||||
_pitch -= r;
|
||||
|
||||
//Console.WriteLine(_pitch._radius);
|
||||
//Console.WriteLine(rotationAtt);
|
||||
InternalPitch();
|
||||
}
|
||||
|
||||
public void Row( Radius r )
|
||||
{
|
||||
_row -= r;
|
||||
|
||||
//Console.WriteLine(_row._radius);
|
||||
//Console.WriteLine(rotationAtt);
|
||||
InternalRow();
|
||||
}
|
||||
|
||||
internal void InternalPitch()
|
||||
{
|
||||
_isLookAtAvailable = false;
|
||||
|
||||
Matrix32 partialCoord = new Matrix32( cameraAtt.colum1.vec, cameraAtt.colum2.vec );
|
||||
float angle = _pitch._radius;
|
||||
|
||||
Matrix22 rotation = new Matrix22(
|
||||
Scaler.Cos( angle ), -Scaler.Sin( angle ), Scaler.Sin( angle ),
|
||||
Scaler.Cos( angle ) );
|
||||
|
||||
partialCoord *= rotation;
|
||||
rotationAtt.colum1.reg = partialCoord.colum0.reg;
|
||||
rotationAtt.colum2.reg = partialCoord.colum1.reg;
|
||||
rotationAtt.isTransposed = false;
|
||||
}
|
||||
|
||||
internal void InternalRow()
|
||||
{
|
||||
_isLookAtAvailable = false;
|
||||
|
||||
Matrix32 partialCoord = new Matrix32( cameraAtt.colum0.vec, cameraAtt.colum1.vec );
|
||||
float angle = _row._radius;
|
||||
|
||||
Matrix22 rotation = new Matrix22(
|
||||
Scaler.Cos( angle ), -Scaler.Sin( angle ), Scaler.Sin( angle ),
|
||||
Scaler.Cos( angle ) );
|
||||
|
||||
partialCoord *= rotation;
|
||||
rotationAtt.colum0.reg = partialCoord.colum0.reg;
|
||||
rotationAtt.colum1.reg = partialCoord.colum1.reg;
|
||||
rotationAtt.isTransposed = false;
|
||||
}
|
||||
|
||||
internal void InternalYaw()
|
||||
{
|
||||
_isLookAtAvailable = false;
|
||||
|
||||
Matrix32 partialCoord = new Matrix32( cameraAtt.colum0.vec, cameraAtt.colum2.vec );
|
||||
float angle = _yaw._radius;
|
||||
Matrix22 rotation = new Matrix22(
|
||||
Scaler.Cos( angle ), -Scaler.Sin( angle ), Scaler.Sin( angle ),
|
||||
Scaler.Cos( angle ) );
|
||||
|
||||
partialCoord *= rotation;
|
||||
rotationAtt.colum0.reg = partialCoord.colum0.reg;
|
||||
rotationAtt.colum2.reg = partialCoord.colum1.reg;
|
||||
rotationAtt.isTransposed = false;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec2HP.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math.HighPrecision
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 16)]
|
||||
public struct Vec2HP : IFixedVector<Vec2HP>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] private M256 buffer;
|
||||
[FieldOffset(0)] private Vector256<float> clrBuffer;
|
||||
|
||||
[FieldOffset(0 * sizeof(double))] public double X;
|
||||
[FieldOffset(1 * sizeof(double))] public double Y;
|
||||
|
||||
public Vec2HP(double x, double y)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Unsafe.SkipInit(out clrBuffer);
|
||||
}
|
||||
|
||||
public static Vec2HP Zero => new Vec2HP(0, 0);
|
||||
|
||||
public static Vec2HP One => new Vec2HP(1, 1);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec3HP.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math.HighPrecision
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Pack = 16)]
|
||||
public struct Vec3HP : IFixedVector<Vec3HP>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] internal M256 buffer;
|
||||
[FieldOffset(0)] internal Vector256<float> clrBuffer;
|
||||
[FieldOffset(0 * sizeof(double))] public double X;
|
||||
[FieldOffset(1 * sizeof(double))] public double Y;
|
||||
[FieldOffset(2 * sizeof(double))] public double Z;
|
||||
|
||||
public Vec3HP() : this(0, 0, 0) { }
|
||||
|
||||
public Vec3HP(Vector256<float> clrBuffer)
|
||||
{
|
||||
this.X = 0;
|
||||
this.Y = 0;
|
||||
this.Z = 0;
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Unsafe.SkipInit(out this.clrBuffer);
|
||||
this.clrBuffer = clrBuffer;
|
||||
}
|
||||
|
||||
public Vec3HP(double x, double y, double z)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.Z = z;
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Unsafe.SkipInit(out clrBuffer);
|
||||
}
|
||||
|
||||
public static Vec3HP Zero => new Vec3HP(1, 1, 1);
|
||||
|
||||
public static Vec3HP One => throw new NotImplementedException();
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Double precision 3D Vector<{X},{Y},{Z}>";
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec4HP.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math.HighPrecision
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Pack =16)]
|
||||
public struct Vec4HP : IFixedVector<Vec4HP>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] private M256 buffer;
|
||||
[FieldOffset(0)] private Vector256<float> clrBuffer;
|
||||
[FieldOffset(3 * sizeof(double))] public double W;
|
||||
[FieldOffset(0 * sizeof(double))] public double X;
|
||||
[FieldOffset(1 * sizeof(double))] public double Y;
|
||||
[FieldOffset(2 * sizeof(double))] public double Z;
|
||||
|
||||
public Vec4HP(double x, double y, double z, double w)
|
||||
{
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.Z = z;
|
||||
this.W = w;
|
||||
Unsafe.SkipInit(out buffer);
|
||||
Unsafe.SkipInit(out clrBuffer);
|
||||
}
|
||||
|
||||
public static Vec4HP Zero => new Vec4HP(0, 0, 0, 0);
|
||||
|
||||
public static Vec4HP One => new Vec4HP(1, 1, 1, 1);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Cordination.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public enum CoordinatePlain
|
||||
{
|
||||
|
||||
XY,
|
||||
YZ,
|
||||
XZ,
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IFixedVector.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public interface IFixedVector<TSelf> where TSelf: struct, IFixedVector<TSelf>
|
||||
{
|
||||
|
||||
public static abstract TSelf Zero { get; }
|
||||
|
||||
public static abstract TSelf One { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IMatrix.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Graphics;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public interface IMatrix<TSelf> where TSelf: IMatrix<TSelf> { }
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="IVector.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public interface IVector<TSelf> where TSelf: struct, IVector<TSelf>
|
||||
{
|
||||
|
||||
public static abstract TSelf Zero { get; }
|
||||
|
||||
public static abstract TSelf One { get; }
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix22.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( 2 * 2 * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix22 : IMatrix<Matrix22>
|
||||
{
|
||||
|
||||
[FieldOffset( 2 * 2 * 4 * sizeof( float ) )]
|
||||
internal bool isTransposed = false;
|
||||
|
||||
[FieldOffset( 0 )]
|
||||
internal ColumnSet2 _mat;
|
||||
[FieldOffset( 2 * 4 * sizeof( float ) )]
|
||||
internal ColumnSet2 _transpose;
|
||||
|
||||
internal Matrix22( ColumnSet2 mat )
|
||||
{
|
||||
this._mat = mat;
|
||||
}
|
||||
|
||||
internal Matrix22( Vector4 c0, Vector4 c1 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
_mat.colum0 = c0;
|
||||
_mat.colum1 = c1;
|
||||
}
|
||||
|
||||
public Matrix22()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix22( float a00, float a01, float a10, float a11 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
_mat.colum0 = new Vector4( a00, a10, 0, 0 );
|
||||
_mat.colum1 = new Vector4( a01, a11, 0, 0 );
|
||||
}
|
||||
|
||||
public Matrix22 Transpose
|
||||
{
|
||||
get
|
||||
{
|
||||
InternalTranspose();
|
||||
return new Matrix22( this._transpose );
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public float Det()
|
||||
{
|
||||
return ( _mat.m00 * _mat.m11 ) - ( _mat.m10 * _mat.m01 );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
_transpose = _mat;
|
||||
float cache = _transpose.m10;
|
||||
_transpose.m10 = _transpose.m01;
|
||||
_transpose.m01 = cache;
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix22 operator -( Matrix22 left, Matrix22 right )
|
||||
{
|
||||
Matrix22 ret = new Matrix22();
|
||||
InternalIO.Intrinsic.sub_mat_2( &left._mat, &right._mat, &ret._mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix22 operator *( Matrix22 mat, float value )
|
||||
{
|
||||
return new Matrix22( mat._mat.colum0 * value, mat._mat.colum1 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix22 operator *( Matrix22 left, Matrix22 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix22(
|
||||
Vector4.Dot( left._transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum1, right._mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix23 operator *( Matrix22 left, Matrix23 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix23(
|
||||
Vector4.Dot( left._transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right._mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum1, right._mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum1, right._mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix24 operator *( Matrix22 left, Matrix24 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix24(
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left._transpose.colum1, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix22 operator /( Matrix22 mat, float value )
|
||||
{
|
||||
return new Matrix22( mat._mat.colum0 / value, mat._mat.colum1 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix22 operator +( Matrix22 left, Matrix22 right )
|
||||
{
|
||||
Matrix22 ret = new Matrix22();
|
||||
InternalIO.Intrinsic.add_mat_2( &left._mat, &right._mat, &ret._mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix23.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( ( 3 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix23 : IMatrix<Matrix23>
|
||||
{
|
||||
|
||||
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed = false;
|
||||
[FieldOffset( 3 * 4 * sizeof( float ) )] internal ColumnSet2 _transpose;
|
||||
[FieldOffset( 0 )] internal ColumnSet3 _mat;
|
||||
|
||||
internal Matrix23( Vector4 c0, Vector4 c1, Vector4 c2 )
|
||||
{
|
||||
_mat.colum0 = c0;
|
||||
_mat.colum1 = c1;
|
||||
_mat.colum2 = c2;
|
||||
}
|
||||
|
||||
public Matrix23()
|
||||
{
|
||||
Unsafe.SkipInit( out _mat );
|
||||
Unsafe.SkipInit( out _transpose );
|
||||
}
|
||||
|
||||
public Matrix23( float a00, float a01, float a02, float a10, float a11, float a12 )
|
||||
{
|
||||
_mat.colum0 = new Vector4( a00, a10, 0, 0 );
|
||||
_mat.colum1 = new Vector4( a01, a11, 0, 0 );
|
||||
_mat.colum2 = new Vector4( a02, a12, 0, 0 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 1 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this._transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 1 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this._transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet3* source = &this._mat )
|
||||
{
|
||||
fixed( ColumnSet2* target = &this._transpose ) {
|
||||
InternalIO.Intrinsic.transpose32( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix23 operator -( Matrix23 left, Matrix23 right )
|
||||
{
|
||||
Matrix23 ret = new Matrix23();
|
||||
InternalIO.Intrinsic.sub_mat_3( &left._mat, &right._mat, &ret._mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix23 operator *( Matrix23 mat, float value )
|
||||
{
|
||||
return new Matrix23(
|
||||
mat._mat.colum0 * value, mat._mat.colum1 * value, mat._mat.colum2 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix22 operator *( Matrix23 left, Matrix32 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix22(
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix23 operator *( Matrix23 left, Matrix33 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix23(
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix24 operator *( Matrix23 left, Matrix34 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix24(
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left._transpose.colum0, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix23 operator /( Matrix23 mat, float value )
|
||||
{
|
||||
return new Matrix23(
|
||||
mat._mat.colum0 / value, mat._mat.colum1 / value, mat._mat.colum2 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix23 operator +( Matrix23 left, Matrix23 right )
|
||||
{
|
||||
Matrix23 ret = new Matrix23();
|
||||
InternalIO.Intrinsic.add_mat_3( &left._mat, &right._mat, &ret._mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix24.cs"
|
||||
// Project: World
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( ( 4 + 2 ) * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix24 : IMatrix<Matrix24>
|
||||
{
|
||||
|
||||
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
|
||||
[FieldOffset( 4 * 4 * sizeof( float ) )] internal ColumnSet2 transpose;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet4 mat;
|
||||
|
||||
[FieldOffset( 0 )] public Vec2 Colum0;
|
||||
[FieldOffset( 16 )] public Vec2 Colum1;
|
||||
[FieldOffset( 32 )] public Vec2 Colum2;
|
||||
[FieldOffset( 48 )] public Vec2 Colum3;
|
||||
|
||||
internal Matrix24( Vector4 c0, Vector4 c1, Vector4 c2, Vector4 c3 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
mat.colum2 = c2;
|
||||
mat.colum3 = c3;
|
||||
}
|
||||
|
||||
public Matrix24()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix24(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a03,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a13 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, 0, 0 );
|
||||
mat.colum1 = new Vector4( a01, a11, 0, 0 );
|
||||
mat.colum2 = new Vector4( a02, a12, 0, 0 );
|
||||
mat.colum3 = new Vector4( a03, a13, 0, 0 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 1 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 ) {
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 1 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 ) {
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
InternalTranspose();
|
||||
return $"{$"[{mat.m00},{mat.m01},{mat.m02},{mat.m03}],"}{$"[{mat.m10},{mat.m11},{mat.m12},{mat.m13}]"}";
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed ) {
|
||||
fixed( ColumnSet4* source = &this.mat ) {
|
||||
fixed( ColumnSet2* target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose42( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix24 operator -(
|
||||
Matrix24 left,
|
||||
Matrix24 right )
|
||||
{
|
||||
Matrix24 ret = new Matrix24();
|
||||
InternalIO.Intrinsic.sub_mat_4( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix24 operator *( Matrix24 mat, float value )
|
||||
{
|
||||
return new Matrix24(
|
||||
mat.mat.colum0 * value, mat.mat.colum1 * value,
|
||||
mat.mat.colum2 * value, mat.mat.colum3 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix22 operator *( Matrix24 left, Matrix42 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix22(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix23 operator *( Matrix24 left, Matrix43 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix23(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix24 operator *( Matrix24 left, Matrix44 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix24(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix24 operator /( Matrix24 mat, float value )
|
||||
{
|
||||
return new Matrix24(
|
||||
mat.mat.colum0 / value, mat.mat.colum1 / value,
|
||||
mat.mat.colum2 / value, mat.mat.colum3 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix24 operator +(
|
||||
Matrix24 left,
|
||||
Matrix24 right )
|
||||
{
|
||||
Matrix24 ret = new Matrix24();
|
||||
InternalIO.Intrinsic.add_mat_4( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix32.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( 5 * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix32 : IMatrix<Matrix32>
|
||||
{
|
||||
|
||||
[FieldOffset( 5 * 4 * sizeof( float ) )] internal bool isTransposed;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet2 mat;
|
||||
[FieldOffset( 2 * 4 * sizeof( float ) )] internal ColumnSet3 transpose;
|
||||
|
||||
[FieldOffset( 0 )] internal Vec3 colum0;
|
||||
[FieldOffset( 4 * 4 )] internal Vec3 colum1;
|
||||
|
||||
internal Matrix32( Vector4 c0, Vector4 c1 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
}
|
||||
|
||||
public Matrix32()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public unsafe Matrix32( float a00, float a01, float a10, float a11, float a20, float a21 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, 0 );
|
||||
mat.colum1 = new Vector4( a01, a11, a21, 0 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 1 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 1 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3 VerticalVecMultiply( Vec2 vec )
|
||||
{
|
||||
return ( colum0 * vec.X ) + ( colum1 * vec.Y );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet2* source = &this.mat )
|
||||
{
|
||||
fixed( ColumnSet3* target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose23( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator -( Matrix32 left, Matrix32 right )
|
||||
{
|
||||
return new Matrix32(
|
||||
left.mat.colum0 - right.mat.colum0, left.mat.colum1 - right.mat.colum1 );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator *( Matrix32 mat, float value )
|
||||
{
|
||||
return new Matrix32( mat.mat.colum0 * value, mat.mat.colum1 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator *( Matrix32 left, Matrix22 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix32(
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix33 operator *( Matrix32 left, Matrix23 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix33(
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix34 operator *( Matrix32 left, Matrix24 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix34(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator /( Matrix32 mat, float value )
|
||||
{
|
||||
return new Matrix32( mat.mat.colum0 / value, mat.mat.colum1 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix32 operator +( Matrix32 left, Matrix32 right )
|
||||
{
|
||||
Matrix32 ret = new Matrix32();
|
||||
InternalIO.Intrinsic.add_mat_2( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix33.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( 6 * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix33 : IMatrix<Matrix33>
|
||||
{
|
||||
|
||||
[FieldOffset( 6 * 4 * sizeof( float ) )] internal bool isTransposed;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet3 mat;
|
||||
[FieldOffset( 3 * 4 * sizeof( float ) )] internal ColumnSet3 transpose;
|
||||
[FieldOffset( 0 * 4 * sizeof( float ) )] public Vec3 Colum0;
|
||||
[FieldOffset( 1 * 4 * sizeof( float ) )] public Vec3 Colum1;
|
||||
[FieldOffset( 2 * 4 * sizeof( float ) )] public Vec3 Colum2;
|
||||
|
||||
internal Matrix33( Vector4 c0, Vector4 c1, Vector4 c2 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
mat.colum2 = c2;
|
||||
}
|
||||
|
||||
public Matrix33()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix33(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a20,
|
||||
float a21,
|
||||
float a22 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, 0 );
|
||||
mat.colum1 = new Vector4( a01, a11, a21, 0 );
|
||||
mat.colum2 = new Vector4( a02, a12, a22, 0 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
InternalIO.InternalWriteLog(
|
||||
$"Attempt to write unused space in {GetType().Name} {nameof(mat)}",
|
||||
LogType.Error );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public unsafe float Det()
|
||||
{
|
||||
fixed( ColumnSet3* mat = &this.mat ) {
|
||||
return InternalIO.Intrinsic.det_mat_3( mat, ( ColumnSet3* )0 );
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet3* source = &this.mat, target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose33( source, target );
|
||||
}
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix33 operator -( Matrix33 left, Matrix33 right )
|
||||
{
|
||||
Matrix33 ret = new Matrix33();
|
||||
InternalIO.Intrinsic.sub_mat_3( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix33 operator *( Matrix33 mat, float value )
|
||||
{
|
||||
return new Matrix33(
|
||||
mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Vec3 operator *( Matrix33 left, Vec3 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Vec3(
|
||||
Vector4.Dot( left.transpose.colum0, right.reg.AsVector4() ),
|
||||
Vector4.Dot( left.transpose.colum1, right.reg.AsVector4() ),
|
||||
Vector4.Dot( left.transpose.colum2, right.reg.AsVector4() ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator *( Matrix33 left, Matrix32 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix32(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix33 operator *( Matrix33 left, Matrix33 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix33(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix34 operator *( Matrix33 left, Matrix34 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix34(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix33 operator /( Matrix33 mat, float value )
|
||||
{
|
||||
return new Matrix33(
|
||||
mat.mat.colum0 / value, mat.mat.colum1 / value, mat.mat.colum2 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix33 operator +( Matrix33 left, Matrix33 right )
|
||||
{
|
||||
Matrix33 ret = new Matrix33();
|
||||
InternalIO.Intrinsic.add_mat_3( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix34.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix34 : IMatrix<Matrix34>
|
||||
{
|
||||
|
||||
[FieldOffset( 7 * 4 * sizeof( float ) )] internal bool isTransposed;
|
||||
[FieldOffset( 4 * 4 * sizeof( float ) )] internal ColumnSet3 transpose;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet4 mat;
|
||||
|
||||
[FieldOffset( 0 * 4 * sizeof( float ) )] public Vec3 Colum0;
|
||||
[FieldOffset( 1 * 4 * sizeof( float ) )] public Vec3 Colum1;
|
||||
[FieldOffset( 2 * 4 * sizeof( float ) )] public Vec3 Colum2;
|
||||
[FieldOffset( 3 * 4 * sizeof( float ) )] public Vec3 Colum3;
|
||||
|
||||
internal Matrix34( ColumnSet4 mat )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
internal Matrix34( Vector4 c0, Vector4 c1, Vector4 c2, Vector4 c3 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
mat.colum2 = c2;
|
||||
mat.colum3 = c3;
|
||||
}
|
||||
|
||||
public Matrix34()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix34(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a03,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a13,
|
||||
float a20,
|
||||
float a21,
|
||||
float a22,
|
||||
float a23 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, 0 );
|
||||
mat.colum0 = new Vector4( a01, a11, a21, 0 );
|
||||
mat.colum0 = new Vector4( a02, a12, a22, 0 );
|
||||
mat.colum0 = new Vector4( a03, a13, a23, 0 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 2 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet4* source = &this.mat )
|
||||
{
|
||||
fixed( ColumnSet3* target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose43( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix34 operator -( Matrix34 left, Matrix34 right )
|
||||
{
|
||||
Matrix34 ret = new Matrix34();
|
||||
InternalIO.Intrinsic.sub_mat_4( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix34 operator *( Matrix34 mat, float value )
|
||||
{
|
||||
return new Matrix34(
|
||||
mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value,
|
||||
mat.mat.colum3 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix32 operator *( Matrix34 left, Matrix42 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix32(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix33 operator *( Matrix34 left, Matrix43 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix33(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix34 operator *( Matrix34 left, Matrix44 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix34(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix34 operator /( Matrix34 mat, float value )
|
||||
{
|
||||
return new Matrix34(
|
||||
mat.mat.colum0 / value, mat.mat.colum1 / value, mat.mat.colum2 / value,
|
||||
mat.mat.colum3 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix34 operator +( Matrix34 left, Matrix34 right )
|
||||
{
|
||||
Matrix34 ret = new Matrix34();
|
||||
InternalIO.Intrinsic.add_mat_4( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix42.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( ( 16 + 8 ) * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix42 : IMatrix<Matrix42>
|
||||
{
|
||||
|
||||
[FieldOffset( ( 16 + 8 ) * sizeof( float ) )] internal bool isTransposed;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet2 mat;
|
||||
[FieldOffset( 8 * sizeof( float ) )] internal ColumnSet4 transpose;
|
||||
|
||||
internal Matrix42( ColumnSet2 mat )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
internal Matrix42( Vector4 c0, Vector4 c1 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
}
|
||||
|
||||
public Matrix42()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix42(
|
||||
float a00,
|
||||
float a01,
|
||||
float a10,
|
||||
float a11,
|
||||
float a20,
|
||||
float a21,
|
||||
float a30,
|
||||
float a31 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, a30 );
|
||||
mat.colum1 = new Vector4( a01, a11, a21, a31 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 1 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 1 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine( mat.colum0.GetHashCode(), mat.colum1.GetHashCode() );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet2* source = &this.mat )
|
||||
{
|
||||
fixed( ColumnSet4* target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose24( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix42 operator -( Matrix42 left, Matrix42 right )
|
||||
{
|
||||
Matrix42 ret = new Matrix42();
|
||||
InternalIO.Intrinsic.sub_mat_2( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix42 operator *( Matrix42 mat, float value )
|
||||
{
|
||||
return new Matrix42( mat.mat.colum0 * value, mat.mat.colum1 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix42 operator *( Matrix42 left, Matrix22 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix42(
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right._mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix43 operator *( Matrix42 left, Matrix23 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix43(
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right._mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right._mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right._mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum3, right._mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix44 operator *( Matrix42 left, Matrix24 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix44(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix42 operator /( Matrix42 mat, float value )
|
||||
{
|
||||
return new Matrix42( mat.mat.colum0 / value, mat.mat.colum1 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix42 operator +( Matrix42 left, Matrix42 right )
|
||||
{
|
||||
Matrix42 ret = new Matrix42();
|
||||
InternalIO.Intrinsic.add_mat_2( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,267 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix43.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
layoutKind: LayoutKind.Explicit,
|
||||
Size = ( 7 * 4 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public struct Matrix43 : IEquatable<Matrix43>, IMatrix<Matrix43>
|
||||
{
|
||||
|
||||
[FieldOffset( 7 * 4 * sizeof( float ) )]
|
||||
internal bool isTransposed;
|
||||
|
||||
[FieldOffset( 0 )]
|
||||
internal ColumnSet3 mat;
|
||||
[FieldOffset( 3 * 4 * sizeof( float ) )]
|
||||
internal ColumnSet4 transpose;
|
||||
|
||||
internal Matrix43( Vector4 c0, Vector4 c1, Vector4 c2 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = c0;
|
||||
mat.colum1 = c1;
|
||||
mat.colum2 = c2;
|
||||
}
|
||||
|
||||
public Matrix43()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public Matrix43(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a20,
|
||||
float a21,
|
||||
float a22,
|
||||
float a30,
|
||||
float a31,
|
||||
float a32 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, a30 );
|
||||
mat.colum1 = new Vector4( a01, a11, a21, a31 );
|
||||
mat.colum2 = new Vector4( a02, a12, a22, a32 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 2 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals( object? obj )
|
||||
{
|
||||
return ( obj is Matrix43 x ) && Equals( x );
|
||||
}
|
||||
|
||||
public bool Equals( Matrix43 other )
|
||||
{
|
||||
return EqualityComparer<ColumnSet3>.Default.Equals( mat, other.mat );
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(
|
||||
mat.colum0.GetHashCode(), mat.colum1.GetHashCode(), mat.colum2.GetHashCode() );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet3* source = &this.mat )
|
||||
{
|
||||
fixed( ColumnSet4* target = &this.transpose ) {
|
||||
InternalIO.Intrinsic.transpose34( source, target );
|
||||
}
|
||||
}
|
||||
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix43 operator -( Matrix43 left, Matrix43 right )
|
||||
{
|
||||
return new Matrix43(
|
||||
left.mat.colum0 - right.mat.colum0, left.mat.colum1 - right.mat.colum1,
|
||||
left.mat.colum2 - right.mat.colum2 );
|
||||
}
|
||||
|
||||
public static bool operator !=( Matrix43 left, Matrix43 right )
|
||||
{
|
||||
return !( left == right );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix43 operator *( Matrix43 mat, float value )
|
||||
{
|
||||
return new Matrix43(
|
||||
mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix42 operator *( Matrix43 left, Matrix32 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix42(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum1 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix43 operator *( Matrix43 left, Matrix33 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix43(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum2 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix44 operator *( Matrix43 left, Matrix34 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix44(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix43 operator /( Matrix43 mat, float value )
|
||||
{
|
||||
return new Matrix43(
|
||||
mat.mat.colum0 / value, mat.mat.colum1 / value, mat.mat.colum2 / value );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix43 operator +( Matrix43 left, Matrix43 right )
|
||||
{
|
||||
Matrix43 ret = new Matrix43();
|
||||
InternalIO.Intrinsic.add_mat_3( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool operator ==( Matrix43 left, Matrix43 right )
|
||||
{
|
||||
return left.Equals( right );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Matrix44.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(
|
||||
LayoutKind.Explicit,
|
||||
Size = ( 2 * 16 * sizeof( float ) ) + sizeof( bool ),
|
||||
Pack = 16 )]
|
||||
public unsafe struct Matrix44 : IEquatable<Matrix44>, IMatrix<Matrix44>
|
||||
{
|
||||
|
||||
[FieldOffset( 2 * 64 * sizeof( float ) )] internal bool isTransposed;
|
||||
|
||||
[FieldOffset( 0 )] internal ColumnSet4 mat;
|
||||
[FieldOffset( 16 * sizeof( float ) )] internal ColumnSet4 transpose;
|
||||
[FieldOffset( 0 * sizeof( float ) )] internal Vec4 colum0;
|
||||
[FieldOffset( 4 * sizeof( float ) )] internal Vec4 colum1;
|
||||
[FieldOffset( 8 * sizeof( float ) )] internal Vec4 colum2;
|
||||
[FieldOffset( 12 * sizeof( float ) )] internal Vec4 colum3;
|
||||
|
||||
internal Matrix44( ColumnSet4 mat )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
this.mat = mat;
|
||||
}
|
||||
|
||||
internal Matrix44( Vector4 vec0, Vector4 vec1, Vector4 vec2, Vector4 vec3 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = vec0;
|
||||
mat.colum1 = vec1;
|
||||
mat.colum2 = vec2;
|
||||
mat.colum3 = vec3;
|
||||
}
|
||||
|
||||
public Matrix44()
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
}
|
||||
|
||||
public unsafe Matrix44(
|
||||
float a00,
|
||||
float a01,
|
||||
float a02,
|
||||
float a03,
|
||||
float a10,
|
||||
float a11,
|
||||
float a12,
|
||||
float a13,
|
||||
float a20,
|
||||
float a21,
|
||||
float a22,
|
||||
float a23,
|
||||
float a30,
|
||||
float a31,
|
||||
float a32,
|
||||
float a33 )
|
||||
{
|
||||
Unsafe.SkipInit( out this );
|
||||
isTransposed = false;
|
||||
mat.colum0 = new Vector4( a00, a10, a20, a30 );
|
||||
mat.colum1 = new Vector4( a01, a11, a21, a31 );
|
||||
mat.colum2 = new Vector4( a02, a12, a22, a32 );
|
||||
mat.colum3 = new Vector4( a03, a13, a23, a33 );
|
||||
}
|
||||
|
||||
public unsafe float this[ int rowNum, int columNum ]
|
||||
{
|
||||
get
|
||||
{
|
||||
#if DEBUG
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) )
|
||||
{
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
#endif
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
return *( float* )pbit;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
#if DEBUG
|
||||
if( ( rowNum > 3 ) || ( rowNum < 0 ) )
|
||||
{
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
if( ( columNum > 3 ) || ( columNum < 0 ) ) {
|
||||
throw new ArgumentOutOfRangeException( nameof( columNum ) );
|
||||
}
|
||||
#endif
|
||||
InternalTranspose();
|
||||
fixed( float* p = &this.transpose.m00 )
|
||||
{
|
||||
ulong pbit = ( ( ulong )p ) + ( ( ( ulong )sizeof( Vector4 ) ) * ( ( ulong )rowNum ) ) + ( ( ( ulong )sizeof( float ) ) * ( ( ulong )columNum ) );
|
||||
*( float* )pbit = value;
|
||||
}
|
||||
isTransposed = false;
|
||||
}
|
||||
}
|
||||
|
||||
public Matrix44 Transpose
|
||||
{
|
||||
get
|
||||
{
|
||||
InternalTranspose();
|
||||
return new Matrix44( this.transpose );
|
||||
}
|
||||
}
|
||||
|
||||
public static Matrix44 Unit => new Matrix44(
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||
|
||||
public static Matrix44 WNegativeUnit => new Matrix44(
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1 );
|
||||
|
||||
public static Matrix44 XNegativeUnit => new Matrix44(
|
||||
-1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||
|
||||
public static Matrix44 YNegativeUnit => new Matrix44(
|
||||
1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
|
||||
|
||||
public static Matrix44 ZNegativeUnit => new Matrix44(
|
||||
1, 0, 0, 0, 0, 1, 0, 0, 0, 0, -1, 0, 0, 0, 0, 1 );
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public unsafe float Det()
|
||||
{
|
||||
InternalTranspose();
|
||||
fixed( ColumnSet4* _this = &mat, _trans = &transpose ) {
|
||||
return InternalIO.Intrinsic.det_mat_4( _this, _trans );
|
||||
}
|
||||
}
|
||||
|
||||
public override bool Equals( object? obj )
|
||||
{
|
||||
return ( obj is Matrix44 x ) && Equals( x );
|
||||
}
|
||||
|
||||
public bool Equals( Matrix44 other )
|
||||
{
|
||||
return mat.Equals( other.mat );
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCode.Combine(
|
||||
mat.colum0.GetHashCode(), mat.colum1.GetHashCode(), mat.colum2.GetHashCode(),
|
||||
mat.colum3.GetHashCode() );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public unsafe Matrix42 Multiple( in Matrix42 right )
|
||||
{
|
||||
InternalTranspose();
|
||||
Matrix42 ans = new Matrix42();
|
||||
fixed( ColumnSet4* lptr = &transpose )
|
||||
{
|
||||
fixed( Vector4* rptr = &right.mat.colum0 ) {
|
||||
InternalIO.Intrinsic.dot_42( lptr, rptr, &ans.mat.colum0 );
|
||||
}
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
public unsafe Matrix43 Multiple( in Matrix43 right )
|
||||
{
|
||||
InternalTranspose();
|
||||
|
||||
Matrix43 ans = new Matrix43();
|
||||
|
||||
fixed( Vector4* rptr = &right.mat.colum0 )
|
||||
{
|
||||
fixed( ColumnSet4* lptr = &transpose ) {
|
||||
InternalIO.Intrinsic.dot_43( lptr, rptr, &ans.mat.colum0 );
|
||||
}
|
||||
}
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
InternalTranspose();
|
||||
return $"{transpose.colum0}{transpose.colum1}{transpose.colum2}{transpose.colum3}";
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
internal unsafe void InternalTranspose()
|
||||
{
|
||||
if( !isTransposed )
|
||||
{
|
||||
fixed( ColumnSet4* source = &mat, target = &transpose ) {
|
||||
InternalIO.Intrinsic.transpose44( source, target );
|
||||
}
|
||||
isTransposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix44 operator -( Matrix44 left, Matrix44 right )
|
||||
{
|
||||
return new Matrix44(
|
||||
right.mat.colum0 - left.mat.colum0, right.mat.colum1 - left.mat.colum1,
|
||||
right.mat.colum2 - left.mat.colum2, right.mat.colum3 - left.mat.colum3 );
|
||||
}
|
||||
|
||||
public static bool operator !=( Matrix44 left, Matrix44 right )
|
||||
{
|
||||
return !( left == right );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix44 operator *( Matrix44 mat, float value )
|
||||
{
|
||||
return new Matrix44(
|
||||
mat.mat.colum0 * value, mat.mat.colum1 * value, mat.mat.colum2 * value,
|
||||
mat.mat.colum3 * value );
|
||||
}
|
||||
|
||||
[Obsolete(
|
||||
"The operand may cause performance loss, use Matrix.Multiple() method instead.",
|
||||
false )]
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix42 operator *( Matrix44 left, Matrix42 right )
|
||||
{
|
||||
return left.Multiple( right );
|
||||
}
|
||||
|
||||
[Obsolete(
|
||||
"The operand may cause performance loss, use Matrix.Multiple() method instead.",
|
||||
false )]
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix43 operator *( Matrix44 left, Matrix43 right )
|
||||
{
|
||||
return left.Multiple( in right );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static Matrix44 operator *( Matrix44 left, Matrix44 right )
|
||||
{
|
||||
left.InternalTranspose();
|
||||
return new Matrix44(
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum0, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum1, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum2, right.mat.colum3 ),
|
||||
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum0 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum1 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum2 ),
|
||||
Vector4.Dot( left.transpose.colum3, right.mat.colum3 ) );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe Matrix44 operator +( Matrix44 left, Matrix44 right )
|
||||
{
|
||||
Matrix44 ret = new Matrix44();
|
||||
InternalIO.Intrinsic.add_mat_4( &left.mat, &right.mat, &ret.mat );
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool operator ==( Matrix44 left, Matrix44 right )
|
||||
{
|
||||
return left.Equals( right );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="MatrixIndexLabel.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public readonly struct MatrixIndexLabel
|
||||
{
|
||||
|
||||
private readonly bool _isRange;
|
||||
public readonly Range R;
|
||||
|
||||
internal MatrixIndexLabel(Index i)
|
||||
{
|
||||
_isRange = false;
|
||||
R = new Range(i, Index.End);
|
||||
}
|
||||
|
||||
internal MatrixIndexLabel(Range r)
|
||||
{
|
||||
_isRange = true;
|
||||
R = r;
|
||||
}
|
||||
|
||||
public (int offset,int legnth) GetOffsetAndLength(int CountOfCollection)
|
||||
{
|
||||
return _isRange ?
|
||||
R.GetOffsetAndLength(CountOfCollection) : (R.Start.GetOffset(CountOfCollection), 1);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public int Length(int CountOfCollection)
|
||||
{
|
||||
return _isRange ? R.GetOffsetAndLength(CountOfCollection).Length : 1;
|
||||
}
|
||||
|
||||
public int Offset(int CountOfCollection)
|
||||
{
|
||||
return _isRange ?
|
||||
R.GetOffsetAndLength(CountOfCollection).Offset : R.Start
|
||||
.GetOffset(CountOfCollection);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator MatrixIndexLabel(Index i)
|
||||
{
|
||||
return new MatrixIndexLabel(i);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator MatrixIndexLabel(Range r)
|
||||
{
|
||||
return new MatrixIndexLabel(r);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator MatrixIndexLabel(int i)
|
||||
{
|
||||
return new MatrixIndexLabel(i);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec2.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
|
||||
using System.Net.Http.Headers;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
/// <summary>
|
||||
/// A two dimension vector defined by two elements. Vec2 in World are default used as colum
|
||||
/// vector.
|
||||
/// </summary>
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 16)]
|
||||
public struct Vec2 : IFixedVector<Vec2>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] internal unsafe fixed float num[2];
|
||||
|
||||
[FieldOffset(0)]
|
||||
internal M128 reg;
|
||||
|
||||
[FieldOffset(0)]
|
||||
internal Vector2 v;
|
||||
|
||||
[FieldOffset(0)]
|
||||
public float X;
|
||||
[FieldOffset(4)]
|
||||
public float Y;
|
||||
|
||||
internal Vec2(Vector2 vec)
|
||||
{
|
||||
Unsafe.SkipInit(out reg);
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
v = vec;
|
||||
}
|
||||
|
||||
internal Vec2(M128 vec)
|
||||
{
|
||||
Unsafe.SkipInit(out reg);
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
reg = vec;
|
||||
reg.Member<ulong>(1) = 0;
|
||||
}
|
||||
|
||||
public Vec2(float x, float y)
|
||||
{
|
||||
v = new Vector2(x, y);
|
||||
}
|
||||
|
||||
public static Vec2 Unit => new Vec2(1, 1);
|
||||
|
||||
public static Vec2 Zero => new Vec2(0, 0);
|
||||
|
||||
public static Vec2 One
|
||||
{
|
||||
get => new Vec2(1, 1);
|
||||
}
|
||||
|
||||
public Vec2 XY
|
||||
{
|
||||
readonly get => this;
|
||||
set => this = value;
|
||||
}
|
||||
|
||||
public Vec3 XYZ
|
||||
{
|
||||
readonly get => new(reg);
|
||||
set
|
||||
{
|
||||
reg = value.reg;
|
||||
reg.Member<ulong>(1) = 0;
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float Cross(Vec2 right)
|
||||
{
|
||||
return (X * right.Y) - (Y * right.X);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float Dot(Vec2 vec)
|
||||
{
|
||||
return Vector2.Dot(v, vec.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2 operator -(Vec2 left, Vec2 right)
|
||||
{
|
||||
return new Vec2(left.v - right.v);
|
||||
}
|
||||
|
||||
public static bool operator !=(Vec2 left, Vec2 right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
public static Vec2 operator *(Vec2 vec, float value)
|
||||
{
|
||||
return new Vec2(vec.v * value);
|
||||
}
|
||||
public static Vec2 operator *(float value, Vec2 vec)
|
||||
{
|
||||
return new Vec2(vec.v * value);
|
||||
}
|
||||
|
||||
public static Vec2 operator /(Vec2 vec, float value)
|
||||
{
|
||||
return new Vec2(vec.v / value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec2 operator +(Vec2 left, Vec2 right)
|
||||
{
|
||||
return new Vec2(left.v + right.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Vec2 left, Vec2 right)
|
||||
{
|
||||
return left.v == right.v;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static implicit operator Vec2((float, float) tuple)
|
||||
{
|
||||
return new Vec2(tuple.Item1, tuple.Item2);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec3.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 16)]
|
||||
public struct Vec3 : IEquatable<Vec3>, IFixedVector<Vec3>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] internal unsafe fixed float num[3];
|
||||
[FieldOffset(0)] internal M128 reg;
|
||||
|
||||
[FieldOffset(0)] internal Vector3 v;
|
||||
|
||||
[FieldOffset(0)] public float X;
|
||||
[FieldOffset(4)] public float Y;
|
||||
[FieldOffset(8)] public float Z;
|
||||
|
||||
internal Vec3(M128 vector)
|
||||
{
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
Unsafe.SkipInit(out v);
|
||||
reg = vector;
|
||||
reg.Member<uint>(3) = 0;
|
||||
}
|
||||
|
||||
internal Vec3(Vector3 vector)
|
||||
{
|
||||
v = vector;
|
||||
}
|
||||
|
||||
public Vec3(Vec2 xy, float z)
|
||||
{
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
Unsafe.SkipInit(out v);
|
||||
reg = xy.reg;
|
||||
Z = z;
|
||||
}
|
||||
|
||||
public Vec3(float x, float y, float z)
|
||||
{
|
||||
Unsafe.SkipInit(out reg);
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
v = new Vector3(x, y, z);
|
||||
}
|
||||
|
||||
public unsafe Vec2 XY
|
||||
{
|
||||
get => new Vec2(this.reg);
|
||||
set
|
||||
{
|
||||
fixed (Vector3* vptr = &v) {
|
||||
*(Vector2*)vptr = value.v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Vec3 XYZ
|
||||
{
|
||||
get => new(v);
|
||||
set => this = value;
|
||||
}
|
||||
|
||||
public static Vec3 Zero => new Vec3(0, 0, 0);
|
||||
|
||||
public static Vec3 One => new Vec3(1, 1, 1);
|
||||
|
||||
public static Vec3 UnitX => new Vec3(1, 0, 0);
|
||||
|
||||
public static Vec3 UnitY => new Vec3(0, 1, 0);
|
||||
|
||||
public static Vec3 UnitZ => new Vec3(0, 0, 1);
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 Cross(Vec3 left, Vec3 right)
|
||||
{
|
||||
return Linear.Cross(left, right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float Dot(Vec3 right)
|
||||
{
|
||||
return Vector3.Dot(v, right.v);
|
||||
}
|
||||
|
||||
public bool Equals(Vec3 other)
|
||||
{
|
||||
return this.reg == other.reg;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (obj is Vec3)
|
||||
{
|
||||
return this == (Vec3)obj;
|
||||
} else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override unsafe int GetHashCode()
|
||||
{
|
||||
fixed (float* add = &X) {
|
||||
return HashCode.Combine(X, Y, Z, (ulong)add);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public float GetMaxValue()
|
||||
{
|
||||
float ret = X;
|
||||
ret = (ret > Y) ? ret : Y;
|
||||
ret = (ret > Z) ? ret : Z;
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static bool IsParallel(Vec3 left, Vec3 right)
|
||||
{
|
||||
return Cross(left, right) == Zero;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"[{X},{Y},{Z}]";
|
||||
}
|
||||
|
||||
public string ToString(string sample)
|
||||
{
|
||||
return $"[{X.ToString(sample)},{Y.ToString(sample)},{Z.ToString(sample)}]";
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 operator -(Vec3 vec)
|
||||
{
|
||||
return new Vec3(-vec.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 operator -(Vec3 left, Vec3 right)
|
||||
{
|
||||
return new Vec3(left.v - right.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator !=(Vec3 left, Vec3 right)
|
||||
{
|
||||
return left.v != right.v;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 operator *(Vec3 vec, float value)
|
||||
{
|
||||
return new Vec3(vec.v * value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static float operator *(Vec3 left, Vec3 right)
|
||||
{
|
||||
return Vector3.Dot(left.v, right.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 operator /(Vec3 vec, float value)
|
||||
{
|
||||
return new Vec3(vec.v / value);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec3 operator +(Vec3 left, Vec3 right)
|
||||
{
|
||||
return new Vec3(left.v + right.v);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool operator ==(Vec3 left, Vec3 right)
|
||||
{
|
||||
return left.v == right.v;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static unsafe implicit operator Vec3((float, float, float) tuple)
|
||||
{
|
||||
Vec3 vec = new Vec3(*(Vector3*)&tuple);
|
||||
return vec;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vec4.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.HighPerformance;
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Data.Common;
|
||||
using System.Numerics;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 16, Pack = 16)]
|
||||
public struct Vec4 : IEquatable<Vec4>, IFixedVector<Vec4>
|
||||
{
|
||||
|
||||
[FieldOffset(0)] internal unsafe fixed float num[4];
|
||||
|
||||
[FieldOffset(0)] internal M128 reg;
|
||||
|
||||
[FieldOffset(0)] internal Vector4 vec;
|
||||
[FieldOffset(12)] public float W;
|
||||
|
||||
[FieldOffset(0)] public float X;
|
||||
[FieldOffset(4)] public float Y;
|
||||
[FieldOffset(8)] public float Z;
|
||||
|
||||
internal Vec4(Vector4 v)
|
||||
{
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
Unsafe.SkipInit(out W);
|
||||
Unsafe.SkipInit(out reg);
|
||||
|
||||
vec = v;
|
||||
}
|
||||
|
||||
internal Vec4(M128 v)
|
||||
{
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
Unsafe.SkipInit(out W);
|
||||
Unsafe.SkipInit(out vec);
|
||||
|
||||
reg = v;
|
||||
}
|
||||
|
||||
public Vec4(Vec3 v3, float w)
|
||||
{
|
||||
Unsafe.SkipInit(out X);
|
||||
Unsafe.SkipInit(out Y);
|
||||
Unsafe.SkipInit(out Z);
|
||||
Unsafe.SkipInit(out W);
|
||||
reg = v3.reg;
|
||||
W = w;
|
||||
}
|
||||
|
||||
public Vec4(float x, float y, float z, float w)
|
||||
{
|
||||
vec = new Vector4(x, y, z, w);
|
||||
}
|
||||
|
||||
public unsafe Vec2 XY
|
||||
{
|
||||
get => new Vec2(reg);
|
||||
set
|
||||
{
|
||||
X = value.X;
|
||||
Y = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe Vec3 XYZ
|
||||
{
|
||||
get => new Vec3(reg);
|
||||
set
|
||||
{
|
||||
float w = W;
|
||||
reg = value.reg;
|
||||
W = w;
|
||||
}
|
||||
}
|
||||
|
||||
public static Vec4 One
|
||||
{
|
||||
get => new Vec4(1, 1, 1, 1);
|
||||
}
|
||||
|
||||
public static Vec4 Zero
|
||||
{
|
||||
get => new Vec4(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4 Add(Vec4 left, Vec4 right)
|
||||
{
|
||||
return left + right;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Vec4 v) ? (v == this) : false;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return vec.GetHashCode();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4 Subtract(Vec4 left, Vec4 right)
|
||||
{
|
||||
return left - right;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return vec.ToString();
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4 operator -(Vec4 left, Vec4 right)
|
||||
{
|
||||
return new Vec4(left.vec - right.vec);
|
||||
}
|
||||
|
||||
public static bool operator !=(Vec4 left, Vec4 right)
|
||||
{
|
||||
return !(left == right);
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4 operator *(Matrix44 mat, Vec4 vec)
|
||||
{
|
||||
mat.InternalTranspose();
|
||||
return new Vec4(
|
||||
Vector4.Dot(mat.transpose.colum0, vec.vec),
|
||||
Vector4.Dot(mat.transpose.colum1, vec.vec),
|
||||
Vector4.Dot(mat.transpose.colum2, vec.vec),
|
||||
Vector4.Dot(mat.transpose.colum3, vec.vec));
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static Vec4 operator +(Vec4 left, Vec4 right)
|
||||
{
|
||||
return new Vec4(left.vec + right.vec);
|
||||
}
|
||||
|
||||
public static bool operator ==(Vec4 left, Vec4 right)
|
||||
{
|
||||
return left.vec == right.vec;
|
||||
}
|
||||
|
||||
bool IEquatable<Vec4>.Equals(Vec4 other)
|
||||
{
|
||||
return vec == other.vec;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="VecAny.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
[CollectionBuilder(typeof(VecAnyBuilder), nameof(VecAnyBuilder.Build))]
|
||||
public class VecAny : IEnumerable<float>
|
||||
{
|
||||
|
||||
private float[] _values;
|
||||
|
||||
internal VecAny(ReadOnlySpan<float> values)
|
||||
{
|
||||
_values = values.ToArray();
|
||||
}
|
||||
|
||||
public VecAny(int size)
|
||||
{
|
||||
if (size <= 0) {
|
||||
throw new ArgumentOutOfRangeException(
|
||||
nameof(size), "Size must be greater than zero.");
|
||||
}
|
||||
_values = new float[size];
|
||||
}
|
||||
|
||||
public VecAny? this[ReadOnlySpan<MatrixIndexLabel> span]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (span.Length == 0) {
|
||||
return null;
|
||||
}
|
||||
int size = 0;
|
||||
foreach (MatrixIndexLabel label in span) {
|
||||
size += label.Length(_values.Length);
|
||||
}
|
||||
return new VecAny(size);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerator<float> GetEnumerator()
|
||||
{
|
||||
return ((IEnumerable<float>)_values).GetEnumerator();
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _values.GetEnumerator();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class VecAnyBuilder
|
||||
{
|
||||
|
||||
public static VecAny Build(ReadOnlySpan<float> span)
|
||||
{
|
||||
return new VecAny(span);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vector.Cross.cs"
|
||||
// Project: World
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Linear
|
||||
{
|
||||
|
||||
public static float Cross( Vec2 vec1, Vec2 vec2 )
|
||||
{
|
||||
return ( vec1.X * vec2.Y ) - ( vec1.Y * vec2.X );
|
||||
}
|
||||
|
||||
public static Vec3 Cross( Vec3 vec1, Vec3 vec2 )
|
||||
{
|
||||
return new Vec3(
|
||||
( vec1.Y * vec2.Z ) - ( vec1.Z * vec2.Y ),
|
||||
( vec1.X * vec2.Z ) - ( vec1.Z * vec2.X ),
|
||||
( vec1.X * vec2.Y ) - ( vec1.Y * vec2.X ) );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vector.GetAngle.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Linear
|
||||
{
|
||||
|
||||
public static float GetAngle( Vec2 vec1, Vec2 vec2 )
|
||||
{
|
||||
return Scaler.ACos(
|
||||
1
|
||||
//vec1.multiple(vec2)
|
||||
/ ( vec1.GetLength() * vec2.GetLength() ) );
|
||||
}
|
||||
|
||||
public static float GetAngle( Vec3 vec1, Vec3 vec2 )
|
||||
{
|
||||
return Scaler.ACos( ( vec1 * vec2 ) / ( vec1.GetLength() * vec2.GetLength() ) );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vector.GetLength.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Linear
|
||||
{
|
||||
|
||||
public static float GetLength( this Vec3 vec )
|
||||
{
|
||||
return Scaler.Sqrt( vec.Dot( vec ) );
|
||||
}
|
||||
|
||||
public static float GetLength( this Vec2 vec )
|
||||
{
|
||||
return Scaler.Sqrt( vec.Dot( vec ) );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vector.Normalize.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal;
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Linear
|
||||
{
|
||||
|
||||
public static Vec4 Normalize( Vec4 vec )
|
||||
{
|
||||
return new Vec4
|
||||
{
|
||||
vec = Vector4.Normalize( vec.vec )
|
||||
};
|
||||
}
|
||||
|
||||
public static Vec3 Normalize( Vec3 vec )
|
||||
{
|
||||
return new Vec3
|
||||
{
|
||||
v = Vector3.Normalize( vec.v )
|
||||
};
|
||||
}
|
||||
|
||||
public static unsafe void Normalize( ref Vec4 source, ref Vec4 target )
|
||||
{
|
||||
Vector4 s = source.vec;
|
||||
Vector4 t = target.vec;
|
||||
|
||||
s = Vector4.Normalize( s );
|
||||
|
||||
float dotProduct = Vector4.Dot( s, t );
|
||||
Vector4 projection = Vector4.Multiply( s, t );
|
||||
|
||||
t -= projection;
|
||||
|
||||
source.vec = s;
|
||||
target.vec = t;
|
||||
}
|
||||
|
||||
public static unsafe void Normalize( ref Vec3 source, ref Vec3 target )
|
||||
{
|
||||
Vector3 s = source.v;
|
||||
Vector3 t = target.v;
|
||||
|
||||
s = Vector3.Normalize( s );
|
||||
Vector3 projection = ( Vector3.Dot( t, s ) / Vector3.Dot( s, s ) ) * s;
|
||||
t -= projection;
|
||||
t = Vector3.Normalize( t );
|
||||
|
||||
source.v = s;
|
||||
target.v = t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Vector.Orthogonalize.cs"
|
||||
// Project: World
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Internal.Intrinsic;
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Linear
|
||||
{
|
||||
|
||||
public static Vec4 Orthogonalize( Vec4 vec )
|
||||
{
|
||||
return new Vec4
|
||||
{
|
||||
vec = Vector4.Normalize( vec.vec )
|
||||
};
|
||||
}
|
||||
|
||||
public static Vec3 Orthogonalize( Vec3 vec )
|
||||
{
|
||||
return new Vec3
|
||||
{
|
||||
v = Vector3.Normalize( vec.v )
|
||||
};
|
||||
}
|
||||
|
||||
public static unsafe void Orthogonalize( ref Vec4 source, ref Vec4 target )
|
||||
{
|
||||
Vector4 s = source.vec;
|
||||
Vector4 t = target.vec;
|
||||
|
||||
s = Vector4.Normalize( s );
|
||||
|
||||
float dotProduct = Vector4.Dot( s, t );
|
||||
Vector4 projection = Vector4.Multiply( s, t );
|
||||
|
||||
t -= projection;
|
||||
|
||||
source.vec = s;
|
||||
target.vec = t;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Orthogonalize two <see cref="Vec3" />s, let their length be 1 and perpendicular to
|
||||
/// each other.
|
||||
/// </summary>
|
||||
/// <param _label="source">
|
||||
///
|
||||
/// </param>
|
||||
/// <param _label="target">
|
||||
///
|
||||
/// </param>
|
||||
public static unsafe void Orthogonalize( ref Vec3 source, ref Vec3 target )
|
||||
{
|
||||
Vector3 s = source.v;
|
||||
Vector3 t = target.v;
|
||||
|
||||
s = Vector3.Normalize( s );
|
||||
Vector3 projection = ( Vector3.Dot( t, s ) / Vector3.Dot( s, s ) ) * s;
|
||||
t -= projection;
|
||||
t = Vector3.Normalize( t );
|
||||
|
||||
source.v = s;
|
||||
target.v = t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="ACos.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe float ACos( float x )
|
||||
{
|
||||
return MathF.Acos( x );
|
||||
|
||||
/*
|
||||
int sign = 1;
|
||||
float y;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
sign = -1;
|
||||
y = -x;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = x;
|
||||
}
|
||||
|
||||
if (x > 1)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
float r, s, u, vec = 0.0f;
|
||||
bool transform = (y >= 0.5f);
|
||||
|
||||
if (transform)
|
||||
{
|
||||
r = 0.5f * (1.0f - y);
|
||||
s = Scaler.Sqrt(r);
|
||||
y = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = y * y;
|
||||
}
|
||||
u = r * (0.184161606965100694821398249421F +
|
||||
(-0.0565298683201845211985026327361F +
|
||||
(-0.0133819288943925804214011424456F -
|
||||
0.00396137437848476485201154797087F * r) * r) * r) /
|
||||
(1.10496961524520294485512696706F -
|
||||
0.836411276854206731913362287293F * r);
|
||||
/*
|
||||
|
||||
if (transform)
|
||||
{
|
||||
float c, s1, p, q;
|
||||
uint us;
|
||||
|
||||
us = *(uint*)&s;
|
||||
uint uss = us & 0xffff0000;
|
||||
s1 = *(float*)&uss;
|
||||
|
||||
c = (r - s1 * s1) / (s + s1);
|
||||
p = 2.0F * s * u - (piby2_tail - 2.0F * c);
|
||||
q = hpiby2_head - 2.0F * s1;
|
||||
vec = hpiby2_head - (p - q);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec = y + y * u;
|
||||
}
|
||||
|
||||
vec = sign * vec;
|
||||
|
||||
return piby2 - vec;
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="ASin.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
private const float
|
||||
piby2_tail = 7.5497894159e-08f, /* 0x33a22168 */
|
||||
hpiby2_head = 7.8539812565e-01f, /* 0x3f490fda */
|
||||
piby2 = 1.5707963705e+00f; /* 0x3fc90fdb */
|
||||
|
||||
/// <summary>
|
||||
/// Reurns the value of ArcSin(x)
|
||||
/// </summary>
|
||||
/// <param _label="x">
|
||||
/// The sine value of the angle
|
||||
/// </param>
|
||||
/// <returns>
|
||||
///
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
///
|
||||
/// </exception>
|
||||
public static float ASin( float x )
|
||||
{
|
||||
return MathF.Asin( x );
|
||||
/*
|
||||
int sign = 1;
|
||||
float y;
|
||||
|
||||
if (x < 0)
|
||||
{
|
||||
sign = -1;
|
||||
y = -x;
|
||||
}
|
||||
else
|
||||
{
|
||||
y = x;
|
||||
}
|
||||
|
||||
if (x > 1)
|
||||
{
|
||||
throw new ArgumentException();
|
||||
}
|
||||
|
||||
float r, s, u, vec = 0.0f;
|
||||
bool transform = (y >= 0.5f);
|
||||
|
||||
if (transform)
|
||||
{
|
||||
r = 0.5f * (1.0f - y);
|
||||
s = Scaler.Sqrt(r);
|
||||
y = s;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = y * y;
|
||||
}
|
||||
u = r * (0.184161606965100694821398249421F +
|
||||
(-0.0565298683201845211985026327361F +
|
||||
(-0.0133819288943925804214011424456F -
|
||||
0.00396137437848476485201154797087F * r) * r) * r) /
|
||||
(1.10496961524520294485512696706F -
|
||||
0.836411276854206731913362287293F * r);
|
||||
/*
|
||||
|
||||
if (transform)
|
||||
{
|
||||
float c, s1, p, q;
|
||||
uint us;
|
||||
|
||||
us = *(uint*)&s;
|
||||
uint uss = us & 0xffff0000;
|
||||
s1 = *(float*)&uss;
|
||||
|
||||
c = (r - s1 * s1) / (s + s1);
|
||||
p = 2.0F * s * u - (piby2_tail - 2.0F * c);
|
||||
q = hpiby2_head - 2.0F * s1;
|
||||
vec = hpiby2_head - (p - q);
|
||||
}
|
||||
else
|
||||
{
|
||||
vec = y + y * u;
|
||||
}/*
|
||||
|
||||
return sign * vec;
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="ATan.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe float ATan( float x )
|
||||
{
|
||||
return MathF.Atan( x );
|
||||
/*
|
||||
float sign = 1, angle = 0;
|
||||
if (x < 0)
|
||||
{
|
||||
sign = -1;
|
||||
x = -x;
|
||||
}
|
||||
uint xBit = *(uint*)&x;
|
||||
int xExp = (int)(xBit >> 23) - 127;
|
||||
if (xExp >= 26)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (xExp <= -15)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
if (xExp >= 0)
|
||||
{
|
||||
x = (x - 1) / (x + 1);
|
||||
angle = 0.7853981634f;
|
||||
}
|
||||
|
||||
float vec = 0.7853981634f * x + x * (1 - x) * (0.2447f + 0.0663f * x);
|
||||
vec += angle;
|
||||
vec *= sign;
|
||||
|
||||
return vec;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static unsafe float ATan(float x, float y)
|
||||
{
|
||||
|
||||
|
||||
float z = y / x;
|
||||
|
||||
float sign = 1, angle = 0, angle2 = 0;
|
||||
if (x < 0)
|
||||
{
|
||||
angle = -3.1415926535f;
|
||||
}
|
||||
if (z < 0)
|
||||
{
|
||||
sign = -1;
|
||||
z = -z;
|
||||
}
|
||||
uint zBit = *(uint*)&z;
|
||||
int zExp = (int)(zBit >> 23) - 127;
|
||||
if (zExp >= 26)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (zExp <= -15)
|
||||
{
|
||||
return z;
|
||||
}
|
||||
if (zExp >= 0)
|
||||
{
|
||||
z = (z - 1) / (z + 1);
|
||||
angle2 = 0.7853981634f;
|
||||
}
|
||||
|
||||
float vec = 0.7853981634f * z + z * (1 - z) * (0.2447f + 0.0663f * z);
|
||||
vec *= 57.29577951f;
|
||||
vec += angle2;
|
||||
vec += angle;
|
||||
vec *= sign;
|
||||
|
||||
return vec;
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="BasicOps.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe float Abs( float x )
|
||||
{
|
||||
uint* a = ( uint* )&x;
|
||||
*a &= 0b_0111_1111_1111_1111_1111_1111_1111_1111;
|
||||
return *( float* )a;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe int Abs( int x )
|
||||
{
|
||||
uint* a = ( uint* )&x;
|
||||
*a &= 0b_0111_1111_1111_1111_1111_1111_1111_1111;
|
||||
return *( int* )a;
|
||||
}
|
||||
|
||||
internal static string GetListSeparator( IFormatProvider formatProvider )
|
||||
{
|
||||
if( formatProvider is CultureInfo cultureInfo ) {
|
||||
return cultureInfo.TextInfo.ListSeparator;
|
||||
}
|
||||
|
||||
if( formatProvider?.GetFormat( typeof( TextInfo ) ) is TextInfo textInfo ) {
|
||||
return textInfo.ListSeparator;
|
||||
}
|
||||
|
||||
return CultureInfo.CurrentCulture.TextInfo.ListSeparator;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Compare.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
public static float MaxOf( params float[] stream )
|
||||
{
|
||||
float ret = stream[ 0 ];
|
||||
foreach( float num in stream )
|
||||
{
|
||||
if( ret < num ) {
|
||||
ret = num;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static float MinOf( params float[] stream )
|
||||
{
|
||||
float ret = stream[ 0 ];
|
||||
foreach( float num in stream )
|
||||
{
|
||||
if( ret > num ) {
|
||||
ret = num;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Cos.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static float Cos( float x )
|
||||
{
|
||||
/*
|
||||
float refer = x / 360.0f;
|
||||
refer -= (int)refer;
|
||||
|
||||
refer *= 40;
|
||||
int a = (int)refer; //大分度,查表
|
||||
refer -= a; //小分度,拟合
|
||||
|
||||
float refer2 = refer * refer;
|
||||
|
||||
|
||||
return ((-sinData[a]) * ((0.1570796327f * refer) - (6.459640975e-4f * refer * refer2)))
|
||||
+ (cosData[a] * ((1 - (0.0123370055f * refer2)) + (2.536695709e-5f * refer2 * refer2)));
|
||||
*/
|
||||
return MathF.Cos( x );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Ctor.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public unsafe delegate float ScalarCalcHandler( float* x );
|
||||
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
private const uint MEM_COMMIT = 0x1000;
|
||||
private const uint MEM_RELEASE = 0x8000;
|
||||
private const uint MEM_RESERVE = 0x2000;
|
||||
private const uint PAGE_EXECUTE_READWRITE = 0x40;
|
||||
|
||||
static Scaler() { }
|
||||
|
||||
[DllImport( "Kernel32.dll", EntryPoint = "VirtualAlloc" )]
|
||||
private static extern IntPtr VirtualAlloc(
|
||||
IntPtr address,
|
||||
int size,
|
||||
uint allocType,
|
||||
uint protect );
|
||||
|
||||
[DllImport( "Kernel32.dll", EntryPoint = "VirtualFree" )]
|
||||
private static extern bool VirtualFree( IntPtr address, int size, uint freeType );
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Exp.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
public const float E = 2.718281828f;
|
||||
public const double EDouble = System.Math.E;
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static float Exp( float x )
|
||||
{
|
||||
return MathF.Exp( x );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static double Exp( double x )
|
||||
{
|
||||
return System.Math.Exp( x );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the value of E ^ x;
|
||||
/// </summary>
|
||||
/// <param _label="x">
|
||||
///
|
||||
/// </param>
|
||||
/// <returns>
|
||||
///
|
||||
/// </returns>
|
||||
public static unsafe float ExpSlow( float x )
|
||||
{
|
||||
if( x == 1 ) {
|
||||
return E;
|
||||
}
|
||||
if( x == 0 ) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool sign = false;
|
||||
if( x < 0 )
|
||||
{
|
||||
sign = true;
|
||||
x = -x;
|
||||
}
|
||||
|
||||
float z = x, t;
|
||||
if( x < 0.5f )
|
||||
{
|
||||
t = 1.0f + ( x * ( 1.0f + ( x * ( 0.5f + ( x * ( 0.1666666667f + ( x * ( 0.0416666666667f + ( x * 8.333333333e-3f ) ) ) ) ) ) ) ) );
|
||||
} else
|
||||
{
|
||||
/*
|
||||
* define z = n * 2 ^ m
|
||||
* n is between 0 and 0.5
|
||||
*/
|
||||
uint zBit = *( uint* )&z;
|
||||
uint zBitAbs = zBit & 0b_0111_1111_1111_1111_1111_1111_1111_1111;
|
||||
uint uintm = zBitAbs >> 23;
|
||||
int m = ( *( int* )&uintm ) - 126;
|
||||
|
||||
|
||||
uint nBit = ( zBitAbs & 0b_0000_0000_0111_1111_1111_1111_1111_1111 ) + 0b_0011_1111_0000_0000_0000_0000_0000_0000;
|
||||
float n = ( *( float* )&nBit ) - 1;
|
||||
|
||||
t = 2.718281828f + ( n * ( 2.718281828f + ( n * ( 1.359140914f + ( n * ( 0.4530469714f + ( n * ( 0.1132617429f + ( n * 0.02265234857f ) ) ) ) ) ) ) ) );
|
||||
|
||||
for( int i = 0; i < m; i++ ) {
|
||||
t = t * t;
|
||||
}
|
||||
}
|
||||
|
||||
if( sign ) {
|
||||
t = 1 / t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Factorial.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
private static readonly uint[] factorialResult = [1, 1, 2, 6, 24,120,720,5040,40320,362880,3628800,39916800,479001600];
|
||||
|
||||
public static unsafe ulong Factorial( int n )
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfLessThan( n, 0 );
|
||||
if( n < 13 ) {
|
||||
return factorialResult[ n ];
|
||||
}
|
||||
if( n < 30 ) {
|
||||
return InternalIO.Intrinsic.factorial_simd( n );
|
||||
}
|
||||
double
|
||||
dn = n,
|
||||
stir = Sqrt( 2 * PiDouble * dn ) * Pow( dn / EDouble, dn ),
|
||||
correction = Exp( 1 / ( 12 * dn ) );
|
||||
return ( ulong )( stir * correction );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Function.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public class Function { }
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Log.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
private static readonly float[] logArray = {
|
||||
0f, 0.00995033085316809f, 0.0198026272961797f, 0.0295588022415444f, 0.0392207131532813f, 0.048790164169432f, 0.0582689081239758f, 0.0676586484738149f, 0.0769610411361284f, 0.0861776962410524f, 0.0953101798043249f, 0.104360015324243f, 0.113328685307003f, 0.122217632724249f, 0.131028262406404f, 0.139761942375159f, 0.148420005118273f, 0.157003748809665f, 0.165514438477573f, 0.173953307123438f, 0.182321556793955f, 0.19062035960865f, 0.198850858745165f, 0.207014169384326f, 0.215111379616945f, 0.22314355131421f, 0.231111720963387f, 0.2390169004705f, 0.246860077931526f, 0.254642218373581f, 0.262364264467491f, 0.27002713721306f, 0.27763173659828f, 0.285178942233662f, 0.29266961396282f, 0.300104592450338f, 0.307484699747961f, 0.314810739840034f, 0.322083499169113f, 0.3293037471426f, 0.336472236621213f, 0.343589704390077f, 0.350656871613169f, 0.357674444271816f, 0.364643113587909f, 0.371563556432483f, 0.378436435720245f, 0.385262400790645f, 0.392042087776024f, 0.398776119957368f, 0.405465108108164f, 0.412109650826833f, 0.418710334858185f, 0.425267735404344f, 0.431782416425538f, 0.438254930931155f, 0.444685821261446f, 0.451075619360217f, 0.457424847038875f, 0.46373401623214f, 0.470003629245736f, 0.476234178996372f, 0.482426149244293f, 0.488580014818671f, 0.494696241836107f, 0.500775287912489f, 0.506817602368452f, 0.512823626428664f, 0.518793793415168f, 0.524728528934982f, 0.53062825106217f, 0.536493370514568f, 0.542324290825362f, 0.548121408509688f, 0.553885113226438f, 0.559615787935423f, 0.56531380905006f, 0.570979546585738f, 0.576613364303994f, 0.582215619852664f, 0.587786664902119f, 0.593326845277734f, 0.598836501088704f, 0.60431596685333f, 0.609765571620894f, 0.615185639090233f, 0.62057648772511f, 0.625938430866495f, 0.631271776841858f, 0.636576829071551f, 0.641853886172395f, 0.647103242058538f, 0.65232518603969f, 0.657520002916794f, 0.662687973075237f, 0.667829372575655f, 0.672944473242426f, 0.678033542749897f, 0.683096844706444f, 0.688134638736401f,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param _label="x">
|
||||
///
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Returns the value of ln(x).
|
||||
/// </returns>
|
||||
public static unsafe float Log( float x )
|
||||
{
|
||||
if( x < 0 ) {
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
uint input = *( uint* )&x;
|
||||
|
||||
int f = ( int )input;
|
||||
f >>= 23;
|
||||
f -= 127;
|
||||
input <<= 9;
|
||||
input >>= 9;
|
||||
input += 0b_0011_1111_1000_0000_0000_0000_0000_0000;
|
||||
float result = *( float* )&input;
|
||||
uint order = ( ( uint )( result * 100 ) ) - 100;
|
||||
|
||||
float cache = ( result / ( 1f + ( 0.01f * order ) ) ) - 1;
|
||||
result = ( cache * ( -0.25f ) ) + 0.3333333333333f;
|
||||
result = ( result * cache ) - 0.5f;
|
||||
result = ( result * cache ) + 1.0f;
|
||||
result *= cache;
|
||||
|
||||
return
|
||||
( f * 0.6931471806f ) + result + logArray[ order ];
|
||||
}
|
||||
|
||||
public static float Log( float x, float y )
|
||||
{
|
||||
return Log( x ) / Log( y );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Pow.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe float Pow( float x, float y )
|
||||
{
|
||||
return System.MathF.Pow( x, y );
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe double Pow( double x, double y )
|
||||
{
|
||||
return System.Math.Pow( x, y );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculate the value of x^y
|
||||
/// </summary>
|
||||
/// <param _label="x">
|
||||
///
|
||||
/// </param>
|
||||
/// <param _label="y">
|
||||
///
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// Returns the value of x^y
|
||||
/// </returns>
|
||||
public static unsafe float PowSlow( float x, float y )
|
||||
{
|
||||
/*
|
||||
* x^y = E ^ ( log( x ) * y )
|
||||
* Now define z = | log(x) * y | = m * n
|
||||
* and m is an integer, and 0.5 < |n| < 1
|
||||
* then E ^ z = ( E ^ n ) ^ m
|
||||
*
|
||||
*
|
||||
* As a float number can be expressed in (1+e)*(2^f)
|
||||
* n = (1+e)/2
|
||||
* m = 2 ^ (f + 1)
|
||||
*
|
||||
*/
|
||||
float z, t;
|
||||
if( ( x == 1 ) || ( y == 0 ) ) {
|
||||
return 1;
|
||||
}
|
||||
if( ( x == 1 ) && ( y == 0 ) ) {
|
||||
return float.PositiveInfinity;
|
||||
}
|
||||
if( ( x == 0 ) && ( y != 0 ) ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
z = Scaler.Log( x ) * y;
|
||||
|
||||
bool sign = false;
|
||||
if( z < 0 )
|
||||
{
|
||||
sign = true;
|
||||
z = -z;
|
||||
}
|
||||
|
||||
if( z < 0.5f )
|
||||
{
|
||||
t = 1.0f + ( z * ( 1.0f + ( z * ( 0.5f + ( z * ( 0.1666666667f + ( z * ( 0.0416666666667f + ( z * 8.333333333e-3f ) ) ) ) ) ) ) ) );
|
||||
} else
|
||||
{
|
||||
uint zBit = *( uint* )&z;
|
||||
uint zBitAbs = zBit & 0b_0111_1111_1111_1111_1111_1111_1111_1111;
|
||||
uint uintm = zBitAbs >> 23;
|
||||
int m = ( *( int* )&uintm ) - 126;
|
||||
|
||||
|
||||
uint nBit = ( zBitAbs & 0b_0000_0000_0111_1111_1111_1111_1111_1111 ) + 0b_0011_1111_0000_0000_0000_0000_0000_0000;
|
||||
float n = ( *( float* )&nBit ) - 1;
|
||||
|
||||
t = 2.718281828f + ( n * ( 2.718281828f + ( n * ( 1.359140914f + ( n * ( 0.4530469714f + ( n * ( 0.1132617429f + ( n * 0.02265234857f ) ) ) ) ) ) ) ) );
|
||||
|
||||
for( int i = 0; i < m; i++ ) {
|
||||
t = t * t;
|
||||
}
|
||||
}
|
||||
if( sign ) {
|
||||
t = 1 / t;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Random.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using StgSharp.Math;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Data;
|
||||
using System.Numerics;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
private static byte[] randomSeed;
|
||||
|
||||
internal static float currentSeed
|
||||
#if DEBUG
|
||||
= 0.5f;
|
||||
|
||||
#else
|
||||
= Abs(System.DateTime.UtcNow.GetHashCode());
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// returns a random float number between 0 and 1.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
///
|
||||
/// </returns>
|
||||
public static unsafe float LowProceisionRandom()
|
||||
{
|
||||
float seed = currentSeed;
|
||||
|
||||
float sample = Scaler.Pow(Scaler.SeedSqrt(seed), 2);
|
||||
float sample2 = (sample - seed) / seed;
|
||||
sample2 = Scaler.Abs(sample2);
|
||||
|
||||
if (sample == 1) {
|
||||
sample = sample2;
|
||||
}
|
||||
|
||||
currentSeed = sample;
|
||||
sample2 *= 1000000;
|
||||
|
||||
float result = sample2 - ((int)sample2);
|
||||
if (result == 0)
|
||||
{
|
||||
currentSeed = sample2 + 0.1f;
|
||||
result = Scaler.LowProceisionRandom();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
///
|
||||
/// </returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static T Random<T>() where T: unmanaged, IConvertible, INumber<T>
|
||||
|
||||
{
|
||||
if (randomSeed == null)
|
||||
{
|
||||
randomSeed = new byte[64];
|
||||
string originSeed =
|
||||
($"{((Assembly.GetEntryAssembly() == null) ? (Assembly.GetAssembly(typeof(World))!) :
|
||||
Assembly.GetEntryAssembly())}") + ($"{DateTime.UtcNow.ToString("o")}");
|
||||
using (SHA256 sha = SHA256.Create()) {
|
||||
randomSeed = sha.ComputeHash(Encoding.UTF8.GetBytes(originSeed));
|
||||
}
|
||||
}
|
||||
using (SHA256 sha = SHA256.Create()) {
|
||||
randomSeed = sha.ComputeHash(randomSeed);
|
||||
}
|
||||
fixed (byte* bptr = randomSeed) {
|
||||
return *(T*)bptr;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generates a random seed in int value.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
///
|
||||
/// </returns>
|
||||
public static unsafe int RandomSeed()
|
||||
{
|
||||
float seedValue1 = LowProceisionRandom();
|
||||
float seedValue2 = LowProceisionRandom();
|
||||
uint seedValueBits = *(uint*)&seedValue1;
|
||||
|
||||
float seedValue = seedValueBits * seedValue2;
|
||||
|
||||
return *(int*)&seedValue;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="SignOf.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static unsafe partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe int SignOf( float x )
|
||||
{
|
||||
if( x == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
if( x > 0 ) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe int SignOf( int x )
|
||||
{
|
||||
if( x == 0 ) {
|
||||
return 0;
|
||||
}
|
||||
if( x > 0 ) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Sin.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
public const float Pi = 3.1415926f;
|
||||
public const double PiDouble = System.Math.PI;
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static unsafe float Sin( float x )
|
||||
{
|
||||
return MathF.Sin( x );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Sqrt.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
public static unsafe float SeedSqrt( float x )
|
||||
{
|
||||
ArgumentOutOfRangeException.ThrowIfNegative( x );
|
||||
if( x <= 1e-12 ) {
|
||||
return 0;
|
||||
}
|
||||
uint a = *( uint* )&x;
|
||||
uint f = a;
|
||||
f >>= 23;
|
||||
f /= 2;
|
||||
f += 64;
|
||||
a -= 0b_0011_1111_0000_0000_0000_0000_0000_0000;
|
||||
uint e = a << 8;
|
||||
e >>= 8;
|
||||
e *= 0b_1101_0001;
|
||||
e >>= 24;
|
||||
e += 0b_0000_0000_0001_0000_1010_1000_1110_0010;
|
||||
f <<= 23;
|
||||
e += f;
|
||||
float result = *( float* )&e;
|
||||
result = ( result + ( x / result ) ) / 2;
|
||||
return ( result + ( x / result ) ) / 2;
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static float Sqrt( float x )
|
||||
{
|
||||
return MathF.Sqrt( x );
|
||||
/**/
|
||||
}
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static double Sqrt( double x )
|
||||
{
|
||||
return System.Math.Sqrt( x );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
// file="Tan.cs"
|
||||
// Project: StgSharp
|
||||
// AuthorGroup: Nitload Space
|
||||
// Copyright (c) Nitload Space. All rights reserved.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person
|
||||
// obtaining a copy of this software and associated documentation
|
||||
// files (the “Software”), to deal in the Software without restriction,
|
||||
// including without limitation the rights to use, copy, modify, merge,
|
||||
// publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
// and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and
|
||||
// this permission notice shall be included in all copies
|
||||
// or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED “AS IS”,
|
||||
// WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
// ARISING FROM, OUT OF OR IN CONNECTION WITH
|
||||
// THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
//
|
||||
//-----------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace StgSharp.Math
|
||||
{
|
||||
public static partial class Scaler
|
||||
{
|
||||
|
||||
[MethodImpl( MethodImplOptions.AggressiveInlining )]
|
||||
public static float Tan( float x )
|
||||
{
|
||||
return MathF.Tan( x );
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -57,4 +57,19 @@ namespace StgSharp.Mathematics
|
||||
public abstract T* UnsafeIndex(int column, int row);
|
||||
|
||||
}
|
||||
|
||||
private unsafe class HlsfMatrix<T> : Matrix<T> where T : unmanaged, INumber<T>
|
||||
{
|
||||
public override ref float this[int column, int row] => throw new NotImplementedException();
|
||||
|
||||
public override unsafe MatrixKernel* GetMatrixKernel(int column, int row)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override unsafe T* UnsafeIndex(int column, int row)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user