using System.Diagnostics; using System.Numerics; using System.Runtime.CompilerServices; namespace Misaki.HighPerformance.HPC; public unsafe struct Vector4 : IEquatable> where TLane : ISPMDLane where TNumber : unmanaged, INumber, IBinaryNumber, IMinMaxValue, IBitwiseOperators { public TLane x; public TLane y; public TLane z; public TLane w; public static Vector4 Zero { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Vector4 { x = TLane.Zero, y = TLane.Zero, z = TLane.Zero, w = TLane.Zero, }; } } public static Vector4 One { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { return new Vector4 { x = TLane.One, y = TLane.One, z = TLane.One, w = TLane.One, }; } } public TLane this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { RangeCheck(index); return Unsafe.Add(ref x, index); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("MHP_ENABLE_SAFETY_CHECKS")] private static void RangeCheck(int index) { if (index < 0 || index >= 4) { throw new IndexOutOfRangeException($"Index {index} is out of range for Vector4."); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store(TNumber* pDst) { x.Store(pDst + 0 * TLane.LaneWidth); y.Store(pDst + 1 * TLane.LaneWidth); z.Store(pDst + 2 * TLane.LaneWidth); w.Store(pDst + 3 * TLane.LaneWidth); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store(ref TNumber dst) { x.Store(ref Unsafe.Add(ref dst, 0 * TLane.LaneWidth)); y.Store(ref Unsafe.Add(ref dst, 1 * TLane.LaneWidth)); z.Store(ref Unsafe.Add(ref dst, 2 * TLane.LaneWidth)); w.Store(ref Unsafe.Add(ref dst, 3 * TLane.LaneWidth)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store(TNumber* px, TNumber* py, TNumber* pz, TNumber* pw) { x.Store(px); y.Store(py); z.Store(pz); w.Store(pw); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store(ref TNumber x, ref TNumber y, ref TNumber z, ref TNumber w) { this.x.Store(ref x); this.y.Store(ref y); this.z.Store(ref z); this.w.Store(ref w); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CompressStore(TNumber* pDst, Vector4 mask) { x.CompressStore(pDst + 0 * TLane.LaneWidth, mask.x); y.CompressStore(pDst + 1 * TLane.LaneWidth, mask.y); z.CompressStore(pDst + 2 * TLane.LaneWidth, mask.z); w.CompressStore(pDst + 3 * TLane.LaneWidth, mask.w); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CompressStore(ref TNumber dst, Vector4 mask) { x.CompressStore(ref Unsafe.Add(ref dst, 0 * TLane.LaneWidth), mask.x); y.CompressStore(ref Unsafe.Add(ref dst, 1 * TLane.LaneWidth), mask.y); z.CompressStore(ref Unsafe.Add(ref dst, 2 * TLane.LaneWidth), mask.z); w.CompressStore(ref Unsafe.Add(ref dst, 3 * TLane.LaneWidth), mask.w); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(TNumber* pDst, TLane indices) { x.Scatter(pDst + 0, indices); y.Scatter(pDst + 1, indices); z.Scatter(pDst + 2, indices); w.Scatter(pDst + 3, indices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(TNumber* pDst, int* pIndices) { x.Scatter(pDst + 0, pIndices); y.Scatter(pDst + 1, pIndices); z.Scatter(pDst + 2, pIndices); w.Scatter(pDst + 3, pIndices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(ref TNumber dst, TLane indices) { x.Scatter(ref Unsafe.Add(ref dst, 0), indices); y.Scatter(ref Unsafe.Add(ref dst, 1), indices); z.Scatter(ref Unsafe.Add(ref dst, 2), indices); w.Scatter(ref Unsafe.Add(ref dst, 3), indices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(ref TNumber dst, int* pIndices) { x.Scatter(ref Unsafe.Add(ref dst, 0), pIndices); y.Scatter(ref Unsafe.Add(ref dst, 1), pIndices); z.Scatter(ref Unsafe.Add(ref dst, 2), pIndices); w.Scatter(ref Unsafe.Add(ref dst, 3), pIndices); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(TNumber* pDst, TLane indices, TLane mask) { x.MaskScatter(pDst + 0, indices, mask); y.MaskScatter(pDst + 1, indices, mask); z.MaskScatter(pDst + 2, indices, mask); w.MaskScatter(pDst + 3, indices, mask); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(TNumber* pDst, int* pIndices, TLane mask) { x.MaskScatter(pDst + 0, pIndices, mask); y.MaskScatter(pDst + 1, pIndices, mask); z.MaskScatter(pDst + 2, pIndices, mask); w.MaskScatter(pDst + 3, pIndices, mask); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(ref TNumber dst, TLane indices, TLane mask) { x.MaskScatter(ref Unsafe.Add(ref dst, 0), indices, mask); y.MaskScatter(ref Unsafe.Add(ref dst, 1), indices, mask); z.MaskScatter(ref Unsafe.Add(ref dst, 2), indices, mask); w.MaskScatter(ref Unsafe.Add(ref dst, 3), indices, mask); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(ref TNumber dst, int* pIndices, TLane mask) { x.MaskScatter(ref Unsafe.Add(ref dst, 0), pIndices, mask); y.MaskScatter(ref Unsafe.Add(ref dst, 1), pIndices, mask); z.MaskScatter(ref Unsafe.Add(ref dst, 2), pIndices, mask); w.MaskScatter(ref Unsafe.Add(ref dst, 3), pIndices, mask); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(in Vector4 vector) { return new Vector4 { x = -vector.x, y = -vector.y, z = -vector.z, w = -vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator +(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x + right.x, y = left.y + right.y, z = left.z + right.z, w = left.w + right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator +(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x + lane, y = vector.y + lane, z = vector.z + lane, w = vector.w + lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator +(TLane lane, in Vector4 vector) { return new Vector4 { x = lane + vector.x, y = lane + vector.y, z = lane + vector.z, w = lane + vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x - right.x, y = left.y - right.y, z = left.z - right.z, w = left.w - right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x - lane, y = vector.y - lane, z = vector.z - lane, w = vector.w - lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator -(TLane lane, in Vector4 vector) { return new Vector4 { x = lane - vector.x, y = lane - vector.y, z = lane - vector.z, w = lane - vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x * right.x, y = left.y * right.y, z = left.z * right.z, w = left.w * right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x * lane, y = vector.y * lane, z = vector.z * lane, w = vector.w * lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator *(TLane lane, in Vector4 vector) { return new Vector4 { x = lane * vector.x, y = lane * vector.y, z = lane * vector.z, w = lane * vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator /(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x / right.x, y = left.y / right.y, z = left.z / right.z, w = left.w / right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator /(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x / lane, y = vector.y / lane, z = vector.z / lane, w = vector.w / lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator /(TLane lane, in Vector4 vector) { return new Vector4 { x = lane / vector.x, y = lane / vector.y, z = lane / vector.z, w = lane / vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator ==(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x == right.x, y = left.y == right.y, z = left.z == right.z, w = left.w == right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator ==(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x == lane, y = vector.y == lane, z = vector.z == lane, w = vector.w == lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator ==(TLane lane, in Vector4 vector) { return new Vector4 { x = lane == vector.x, y = lane == vector.y, z = lane == vector.z, w = lane == vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator !=(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x != right.x, y = left.y != right.y, z = left.z != right.z, w = left.w != right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator !=(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x != lane, y = vector.y != lane, z = vector.z != lane, w = vector.w != lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator !=(TLane lane, in Vector4 vector) { return new Vector4 { x = lane != vector.x, y = lane != vector.y, z = lane != vector.z, w = lane != vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x > right.x, y = left.y > right.y, z = left.z > right.z, w = left.w > right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x > lane, y = vector.y > lane, z = vector.z > lane, w = vector.w > lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >(TLane lane, in Vector4 vector) { return new Vector4 { x = lane > vector.x, y = lane > vector.y, z = lane > vector.z, w = lane > vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >=(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x >= right.x, y = left.y >= right.y, z = left.z >= right.z, w = left.w >= right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >=(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x >= lane, y = vector.y >= lane, z = vector.z >= lane, w = vector.w >= lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator >=(TLane lane, in Vector4 vector) { return new Vector4 { x = lane >= vector.x, y = lane >= vector.y, z = lane >= vector.z, w = lane >= vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x < right.x, y = left.y < right.y, z = left.z < right.z, w = left.w < right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x < lane, y = vector.y < lane, z = vector.z < lane, w = vector.w < lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <(TLane lane, in Vector4 vector) { return new Vector4 { x = lane < vector.x, y = lane < vector.y, z = lane < vector.z, w = lane < vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <=(in Vector4 left, in Vector4 right) { return new Vector4 { x = left.x <= right.x, y = left.y <= right.y, z = left.z <= right.z, w = left.w <= right.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <=(in Vector4 vector, TLane lane) { return new Vector4 { x = vector.x <= lane, y = vector.y <= lane, z = vector.z <= lane, w = vector.w <= lane, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Vector4 operator <=(TLane lane, in Vector4 vector) { return new Vector4 { x = lane <= vector.x, y = lane <= vector.y, z = lane <= vector.z, w = lane <= vector.w, }; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals(Vector4 other) { return this.x.Equals(other.x) && this.y.Equals(other.y) && this.z.Equals(other.z) && this.w.Equals(other.w); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) { return obj is Vector4 other && Equals(other); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly int GetHashCode() { var hash = new HashCode(); hash.Add(x); hash.Add(y); hash.Add(z); hash.Add(w); return hash.ToHashCode(); } }