<#@ import namespace="System.Text" #> <#+ private const string TLane = "TLane"; private const string TNumber = "TNumber"; private string TLaneRestrictions = $@"where {TLane} : ISPMDLane<{TLane}, {TNumber}>"; private string TNumberRestrictions = $@"where {TNumber} : unmanaged, INumber<{TNumber}>, IBinaryNumber<{TNumber}>, IMinMaxValue<{TNumber}>, IBitwiseOperators<{TNumber}, {TNumber}, {TNumber}>"; private int[] dimensions = new int[] { 2, 3, 4 }; private char[] components = new char[] { 'x', 'y', 'z', 'w' }; public string Indent(string str, int spaces) { var indent = new string(' ', spaces); return indent + str; } private string ForEachDimension(int maxDimension, int indentation, string spliter, Action action, bool spliterOnFirst = true) { var sb = new StringBuilder(); for (var dimension = 0; dimension < maxDimension; dimension++) { if ((dimension > 0 || spliterOnFirst) && indentation > 0) { sb.Append(new string(' ', indentation)); } action(dimension, sb); if (dimension < maxDimension - 1) { sb.Append(spliter); } } return sb.ToString(); } public StringBuilder GenerateVectorType(int dimension) { var sb = new StringBuilder(); var typeName = $"Vector{dimension}<{TLane}, {TNumber}>"; sb.AppendLine(@$" public unsafe struct {typeName} : IEquatable<{typeName}> {TLaneRestrictions} {TNumberRestrictions} {{ {ForEachDimension(dimension, 4, Environment.NewLine, (dim, sb) => sb.Append($"public {TLane} {components[dim]};"))} public static {typeName} Zero {{ [MethodImpl(MethodImplOptions.AggressiveInlining)] get {{ return new {typeName} {{ {ForEachDimension(dimension, 16, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = {TLane}.Zero,"))} }}; }} }} public static {typeName} One {{ [MethodImpl(MethodImplOptions.AggressiveInlining)] get {{ return new {typeName} {{ {ForEachDimension(dimension, 16, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = {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 >= {dimension}) {{ throw new IndexOutOfRangeException($""Index {{index}} is out of range for Vector{dimension}.""); }} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store({TNumber}* pDst) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Store(pDst + {dim} * TLane.LaneWidth);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store(ref {TNumber} dst) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Store(ref Unsafe.Add(ref dst, {dim} * TLane.LaneWidth));"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store({ForEachDimension(dimension, 1, ",", (dim, sb) => sb.Append($"{TNumber}* p{components[dim]}"), false)}) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Store(p{components[dim]});"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Store({ForEachDimension(dimension, 1, ",", (dim, sb) => sb.Append($"ref {TNumber} {components[dim]}"), false)}) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"this.{components[dim]}.Store(ref {components[dim]});"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CompressStore({TNumber}* pDst, {typeName} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.CompressStore(pDst + {dim} * TLane.LaneWidth, mask.{components[dim]});"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void CompressStore(ref {TNumber} dst, {typeName} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.CompressStore(ref Unsafe.Add(ref dst, {dim} * TLane.LaneWidth), mask.{components[dim]});"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter({TNumber}* pDst, {TLane} indices) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Scatter(pDst + {dim}, indices);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter({TNumber}* pDst, int* pIndices) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Scatter(pDst + {dim}, pIndices);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(ref {TNumber} dst, {TLane} indices) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Scatter(ref Unsafe.Add(ref dst, {dim}), indices);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void Scatter(ref {TNumber} dst, int* pIndices) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.Scatter(ref Unsafe.Add(ref dst, {dim}), pIndices);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter({TNumber}* pDst, {TLane} indices, {TLane} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.MaskScatter(pDst + {dim}, indices, mask);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter({TNumber}* pDst, int* pIndices, {TLane} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.MaskScatter(pDst + {dim}, pIndices, mask);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(ref {TNumber} dst, {TLane} indices, {TLane} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.MaskScatter(ref Unsafe.Add(ref dst, {dim}), indices, mask);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MaskScatter(ref {TNumber} dst, int* pIndices, {TLane} mask) {{ {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]}.MaskScatter(ref Unsafe.Add(ref dst, {dim}), pIndices, mask);"))} }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator -(in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = -vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator +(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} + right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator +(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} + lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator +({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane + vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator -(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} - right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator -(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} - lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator -({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane - vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator *(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} * right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator *(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} * lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator *({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane * vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator /(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} / right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator /(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} / lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator /({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane / vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator ==(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} == right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator ==(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} == lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator ==({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane == vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator !=(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} != right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator !=(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} != lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator !=({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane != vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} > right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} > lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane > vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >=(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} >= right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >=(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} >= lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator >=({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane >= vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} < right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} < lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane < vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <=(in {typeName} left, in {typeName} right) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = left.{components[dim]} <= right.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <=(in {typeName} vector, {TLane} lane) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = vector.{components[dim]} <= lane,"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public static {typeName} operator <=({TLane} lane, in {typeName} vector) {{ return new {typeName} {{ {ForEachDimension(dimension, 12, Environment.NewLine, (dim, sb) => sb.Append($"{components[dim]} = lane <= vector.{components[dim]},"))} }}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public readonly bool Equals({typeName} other) {{ return {ForEachDimension(dimension, 0, " && ", (dim, sb) => sb.Append($"this.{components[dim]}.Equals(other.{components[dim]})"), false)}; }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly bool Equals(object? obj) {{ return obj is {typeName} other && Equals(other); }} [MethodImpl(MethodImplOptions.AggressiveInlining)] public override readonly int GetHashCode() {{ var hash = new HashCode(); {ForEachDimension(dimension, 8, Environment.NewLine, (dim, sb) => sb.Append($"hash.Add({components[dim]});"))} return hash.ToHashCode(); }} }}"); return sb; } #>