259 lines
12 KiB
C#
259 lines
12 KiB
C#
// -----------------------------------------------------------------------------
|
|
// file="GMatrix44_T"
|
|
// Project: StgSharp
|
|
// Copyright (c) Nitload.
|
|
// SPDX-License-Identifier: MIT
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using Nitload.Mathematics;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Numerics;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Intrinsics;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Nitload.Mathematics.Numeric.Graphics
|
|
{
|
|
[StructLayout(LayoutKind.Sequential, Pack = 16)]
|
|
public struct GMatrix44<T> where T : unmanaged, INumber<T>
|
|
{
|
|
|
|
private Buffer _buffer;
|
|
|
|
internal unsafe ref Vec4<T> this[
|
|
int x
|
|
]
|
|
{
|
|
get => ref Unsafe.Add(ref Unsafe.As<GMatrix44<T>, Vec4<T>>(ref this), x);
|
|
}
|
|
|
|
public T this[
|
|
int x,
|
|
int y
|
|
]
|
|
{
|
|
readonly get => _buffer[x][y];
|
|
set => _buffer[x][y] = value;
|
|
}
|
|
|
|
public static GMatrix44<T> Unit
|
|
{
|
|
get
|
|
{
|
|
GMatrix44<T> result = new();
|
|
result[0] = new Vec4<T>(T.One, T.Zero, T.Zero, T.Zero);
|
|
result[1] = new Vec4<T>(T.Zero, T.One, T.Zero, T.Zero);
|
|
result[2] = new Vec4<T>(T.Zero, T.Zero, T.One, T.Zero);
|
|
result[3] = new Vec4<T>(T.Zero, T.Zero, T.Zero, T.One);
|
|
return result;
|
|
}
|
|
}
|
|
|
|
public GMatrix44<T> Transpose
|
|
{
|
|
get
|
|
{
|
|
GMatrix44<T> transpose = new();
|
|
|
|
// Native SK transpose is intentionally deferred until the module
|
|
// startup path can guarantee that GlobalContext has been initialized.
|
|
|
|
if (Unsafe.SizeOf<T>() == 4)
|
|
{
|
|
Vector128<T> row0Source = _buffer[0].AsVector128Unsafe();
|
|
Vector128<T> row1Source = _buffer[1].AsVector128Unsafe();
|
|
Vector128<T> row2Source = _buffer[2].AsVector128Unsafe();
|
|
Vector128<T> row3Source = _buffer[3].AsVector128Unsafe();
|
|
Vector128<int> row0 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row0Source);
|
|
Vector128<int> row1 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row1Source);
|
|
Vector128<int> row2 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row2Source);
|
|
Vector128<int> row3 = Unsafe.As<Vector128<T>, Vector128<int>>(ref row3Source);
|
|
|
|
Vector128<int> pairMask = Vector128.Create(-1, 0, -1, 0);
|
|
Vector128<int> firstPairMask = Vector128.Create(-1, -1, 0, 0);
|
|
Vector128<int> lowShuffle = Vector128.Create(0, 0, 1, 1);
|
|
Vector128<int> highShuffle = Vector128.Create(2, 2, 3, 3);
|
|
Vector128<int> secondLaneShuffle = Vector128.Create(2, 3, 2, 3);
|
|
|
|
Vector128<int> pair01Low = Vector128.ConditionalSelect(
|
|
pairMask,
|
|
Vector128.Shuffle(row0, lowShuffle),
|
|
Vector128.Shuffle(row1, lowShuffle));
|
|
Vector128<int> pair23Low = Vector128.ConditionalSelect(
|
|
pairMask,
|
|
Vector128.Shuffle(row2, lowShuffle),
|
|
Vector128.Shuffle(row3, lowShuffle));
|
|
Vector128<int> pair01High = Vector128.ConditionalSelect(
|
|
pairMask,
|
|
Vector128.Shuffle(row0, highShuffle),
|
|
Vector128.Shuffle(row1, highShuffle));
|
|
Vector128<int> pair23High = Vector128.ConditionalSelect(
|
|
pairMask,
|
|
Vector128.Shuffle(row2, highShuffle),
|
|
Vector128.Shuffle(row3, highShuffle));
|
|
|
|
Vector128<int> result0 = Vector128.ConditionalSelect(
|
|
firstPairMask, pair01Low, pair23Low);
|
|
Vector128<int> result1 = Vector128.ConditionalSelect(
|
|
firstPairMask,
|
|
Vector128.Shuffle(pair01Low, secondLaneShuffle),
|
|
Vector128.Shuffle(pair23Low, secondLaneShuffle));
|
|
Vector128<int> result2 = Vector128.ConditionalSelect(
|
|
firstPairMask, pair01High, pair23High);
|
|
Vector128<int> result3 = Vector128.ConditionalSelect(
|
|
firstPairMask,
|
|
Vector128.Shuffle(pair01High, secondLaneShuffle),
|
|
Vector128.Shuffle(pair23High, secondLaneShuffle));
|
|
transpose._buffer[0] = Vec4.FromVector128Unsafe(
|
|
Unsafe.As<Vector128<int>, Vector128<T>>(ref result0));
|
|
transpose._buffer[1] = Vec4.FromVector128Unsafe(
|
|
Unsafe.As<Vector128<int>, Vector128<T>>(ref result1));
|
|
transpose._buffer[2] = Vec4.FromVector128Unsafe(
|
|
Unsafe.As<Vector128<int>, Vector128<T>>(ref result2));
|
|
transpose._buffer[3] = Vec4.FromVector128Unsafe(
|
|
Unsafe.As<Vector128<int>, Vector128<T>>(ref result3));
|
|
return transpose;
|
|
}
|
|
|
|
if (Unsafe.SizeOf<T>() == 8)
|
|
{
|
|
Vector256<T> row0Source = _buffer[0].AsVector256Unsafe();
|
|
Vector256<T> row1Source = _buffer[1].AsVector256Unsafe();
|
|
Vector256<T> row2Source = _buffer[2].AsVector256Unsafe();
|
|
Vector256<T> row3Source = _buffer[3].AsVector256Unsafe();
|
|
Vector256<long> row0 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row0Source);
|
|
Vector256<long> row1 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row1Source);
|
|
Vector256<long> row2 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row2Source);
|
|
Vector256<long> row3 = Unsafe.As<Vector256<T>, Vector256<long>>(ref row3Source);
|
|
|
|
Vector256<long> pairMask = Vector256.Create(-1L, 0L, -1L, 0L);
|
|
Vector256<long> firstPairMask = Vector256.Create(-1L, -1L, 0L, 0L);
|
|
Vector256<long> firstShuffle = Vector256.Create(0L, 0L, 1L, 1L);
|
|
Vector256<long> secondShuffle = Vector256.Create(2L, 2L, 3L, 3L);
|
|
Vector256<long> pair01First = Vector256.ConditionalSelect(
|
|
pairMask,
|
|
Vector256.Shuffle(row0, firstShuffle),
|
|
Vector256.Shuffle(row1, firstShuffle));
|
|
Vector256<long> pair23First = Vector256.ConditionalSelect(
|
|
pairMask,
|
|
Vector256.Shuffle(row2, firstShuffle),
|
|
Vector256.Shuffle(row3, firstShuffle));
|
|
Vector256<long> pair01Second = Vector256.ConditionalSelect(
|
|
pairMask,
|
|
Vector256.Shuffle(row0, secondShuffle),
|
|
Vector256.Shuffle(row1, secondShuffle));
|
|
Vector256<long> pair23Second = Vector256.ConditionalSelect(
|
|
pairMask,
|
|
Vector256.Shuffle(row2, secondShuffle),
|
|
Vector256.Shuffle(row3, secondShuffle));
|
|
Vector256<long> result0 = Vector256.ConditionalSelect(
|
|
firstPairMask, pair01First, pair23First);
|
|
Vector256<long> result1 = Vector256.ConditionalSelect(
|
|
firstPairMask,
|
|
Vector256.Shuffle(pair01First, secondShuffle),
|
|
Vector256.Shuffle(pair23First, secondShuffle));
|
|
Vector256<long> result2 = Vector256.ConditionalSelect(
|
|
firstPairMask, pair01Second, pair23Second);
|
|
Vector256<long> result3 = Vector256.ConditionalSelect(
|
|
firstPairMask,
|
|
Vector256.Shuffle(pair01Second, secondShuffle),
|
|
Vector256.Shuffle(pair23Second, secondShuffle));
|
|
transpose._buffer[0] = Vec4.FromVector256Unsafe(
|
|
Unsafe.As<Vector256<long>, Vector256<T>>(ref result0));
|
|
transpose._buffer[1] = Vec4.FromVector256Unsafe(
|
|
Unsafe.As<Vector256<long>, Vector256<T>>(ref result1));
|
|
transpose._buffer[2] = Vec4.FromVector256Unsafe(
|
|
Unsafe.As<Vector256<long>, Vector256<T>>(ref result2));
|
|
transpose._buffer[3] = Vec4.FromVector256Unsafe(
|
|
Unsafe.As<Vector256<long>, Vector256<T>>(ref result3));
|
|
return transpose;
|
|
}
|
|
|
|
throw GraphicVector.ThrowUnsupportedTypeException<T>();
|
|
}
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static GMatrix44<T> operator -(
|
|
GMatrix44<T> left,
|
|
GMatrix44<T> right
|
|
)
|
|
{
|
|
Unsafe.SkipInit(out GMatrix44<T> result);
|
|
result._buffer[0] = left._buffer[0] - right._buffer[0];
|
|
result._buffer[1] = left._buffer[1] - right._buffer[1];
|
|
result._buffer[2] = left._buffer[2] - right._buffer[2];
|
|
result._buffer[3] = left._buffer[3] - right._buffer[3];
|
|
|
|
return result;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static GMatrix44<T> operator *(
|
|
GMatrix44<T> left,
|
|
T right
|
|
)
|
|
{
|
|
Unsafe.SkipInit(out GMatrix44<T> result);
|
|
result._buffer[0] = left._buffer[0] * right;
|
|
result._buffer[1] = left._buffer[1] * right;
|
|
result._buffer[2] = left._buffer[2] * right;
|
|
result._buffer[3] = left._buffer[3] * right;
|
|
|
|
return result;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static GMatrix44<T> operator *(
|
|
T left,
|
|
GMatrix44<T> right
|
|
)
|
|
{
|
|
return right * left;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static GMatrix44<T> operator *(
|
|
GMatrix44<T> left,
|
|
GMatrix44<T> right
|
|
)
|
|
{
|
|
Unsafe.SkipInit(out GMatrix44<T> result);
|
|
result._buffer[0] = left._buffer[0] + right._buffer[0];
|
|
result._buffer[1] = left._buffer[1] + right._buffer[1];
|
|
result._buffer[2] = left._buffer[2] + right._buffer[2];
|
|
result._buffer[3] = left._buffer[3] + right._buffer[3];
|
|
|
|
return result;
|
|
}
|
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
public static GMatrix44<T> operator +(
|
|
GMatrix44<T> left,
|
|
GMatrix44<T> right
|
|
)
|
|
{
|
|
Unsafe.SkipInit(out GMatrix44<T> result);
|
|
result._buffer[0] = left._buffer[0] + right._buffer[0];
|
|
result._buffer[1] = left._buffer[1] + right._buffer[1];
|
|
result._buffer[2] = left._buffer[2] + right._buffer[2];
|
|
result._buffer[3] = left._buffer[3] + right._buffer[3];
|
|
|
|
return result;
|
|
}
|
|
|
|
[InlineArray(4)]
|
|
private struct Buffer
|
|
{
|
|
|
|
public Vec4<T> _column;
|
|
|
|
}
|
|
|
|
}
|
|
}
|