From 07121c737e3d0c905918ab7ef02d74602c1d6ea1 Mon Sep 17 00:00:00 2001 From: Tanner Gooding Date: Wed, 7 Nov 2018 19:15:37 -0800 Subject: [PATCH] Move the various helper intrinsics to be implemented on the S.R.Intrinsics.Vector types (#20147) * Renaming Vector64.cs, Vector128.cs, and Vector256.cs to be Vector64_1.cs, etc * Adding some core helper methods to the Vector64, Vector128, and Vecto256 types. * Adding some documentation comments to the System.Runtime.Intrinsics.Vector types * Changing `Set` to `With` --- .../System.Private.CoreLib.Shared.projitems | 9 +- .../System/Runtime/Intrinsics/Vector128.cs | 861 ++++++++++++- ...28DebugView.cs => Vector128DebugView_1.cs} | 0 .../System/Runtime/Intrinsics/Vector128_1.cs | 278 +++++ .../System/Runtime/Intrinsics/Vector256.cs | 1061 ++++++++++++++++- ...56DebugView.cs => Vector256DebugView_1.cs} | 0 .../System/Runtime/Intrinsics/Vector256_1.cs | 251 ++++ .../System/Runtime/Intrinsics/Vector64.cs | 481 +++++++- ...r64DebugView.cs => Vector64DebugView_1.cs} | 0 .../System/Runtime/Intrinsics/Vector64_1.cs | 226 ++++ 10 files changed, 3067 insertions(+), 100 deletions(-) rename src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/{Vector128DebugView.cs => Vector128DebugView_1.cs} (100%) create mode 100644 src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs rename src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/{Vector256DebugView.cs => Vector256DebugView_1.cs} (100%) create mode 100644 src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs rename src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/{Vector64DebugView.cs => Vector64DebugView_1.cs} (100%) create mode 100644 src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems index 078444fb8f48..c3ef9a3211f1 100644 --- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems @@ -517,11 +517,14 @@ - + + - + + - + + diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs index b2e72ddf8933..f8eefb7dc092 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128.cs @@ -2,43 +2,840 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.Intrinsics { - [Intrinsic] - [DebuggerDisplay("{DisplayString,nq}")] - [DebuggerTypeProxy(typeof(Vector128DebugView<>))] - [StructLayout(LayoutKind.Sequential, Size = 16)] - public readonly struct Vector128 where T : struct + public static class Vector128 { - // These fields exist to ensure the alignment is 8, rather than 1. - // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) - private readonly ulong _00; - private readonly ulong _01; - - private unsafe string DisplayString - { - get - { - // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr` - // which are not actually supported by any current architecture. This shouldn't be - // an issue however and greatly simplifies the check - - if (typeof(T).IsPrimitive) - { - var items = new T[16 / Unsafe.SizeOf()]; - Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); - return $"({string.Join(", ", items)})"; - } - else - { - return SR.NotSupported_Type; - } - } + internal const int Size = 16; + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(byte value) + { + var pResult = stackalloc byte[16] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(double value) + { + var pResult = stackalloc double[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(short value) + { + var pResult = stackalloc short[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(int value) + { + var pResult = stackalloc int[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(long value) + { + var pResult = stackalloc long[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector128 Create(sbyte value) + { + var pResult = stackalloc sbyte[16] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector128 Create(float value) + { + var pResult = stackalloc float[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector128 Create(ushort value) + { + var pResult = stackalloc ushort[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector128 Create(uint value) + { + var pResult = stackalloc uint[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector128 Create(ulong value) + { + var pResult = stackalloc ulong[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15) + { + var pResult = stackalloc byte[16] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(double e0, double e1) + { + var pResult = stackalloc double[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7) + { + var pResult = stackalloc short[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(int e0, int e1, int e2, int e3) + { + var pResult = stackalloc int[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(long e0, long e1) + { + var pResult = stackalloc long[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector128 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7, sbyte e8, sbyte e9, sbyte e10, sbyte e11, sbyte e12, sbyte e13, sbyte e14, sbyte e15) + { + var pResult = stackalloc sbyte[16] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector128 Create(float e0, float e1, float e2, float e3) + { + var pResult = stackalloc float[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector128 Create(ushort e0, ushort e1, ushort e2, ushort e3, ushort e4, ushort e5, ushort e6, ushort e7) + { + var pResult = stackalloc ushort[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector128 Create(uint e0, uint e1, uint e2, uint e3) + { + var pResult = stackalloc uint[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector128 Create(ulong e0, ulong e1) + { + var pResult = stackalloc ulong[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance from two instances. + /// The value that the lower 64-bits will be initialized to. + /// The value that the upper 64-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector128 Create(Vector64 lower, Vector64 upper) + { + Vector128 result128 = Vector128.Zero; + + ref Vector64 result64 = ref Unsafe.As, Vector64>(ref result128); + result64 = lower; + Unsafe.Add(ref result64, 1) = upper; + + return result128; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(byte value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(double value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(short value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(int value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(long value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalar(sbyte value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector128 CreateScalar(float value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalar(ushort value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalar(uint value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalar(ulong value) + { + var result = Vector128.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(byte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc byte[16]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(double value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc double[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(short value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc short[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(int value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc int[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(long value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc long[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalarUnsafe(sbyte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc sbyte[16]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector128 CreateScalarUnsafe(float value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc float[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalarUnsafe(ushort value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc ushort[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalarUnsafe(uint value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc uint[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector128 CreateScalarUnsafe(ulong value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc ulong[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView_1.cs similarity index 100% rename from src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView.cs rename to src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128DebugView_1.cs diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs new file mode 100644 index 000000000000..d8d4095d9d35 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector128_1.cs @@ -0,0 +1,278 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal.Runtime.CompilerServices; + +namespace System.Runtime.Intrinsics +{ + [Intrinsic] + [DebuggerDisplay("{DisplayString,nq}")] + [DebuggerTypeProxy(typeof(Vector128DebugView<>))] + [StructLayout(LayoutKind.Sequential, Size = Vector128.Size)] + public readonly struct Vector128 where T : struct + { + // These fields exist to ensure the alignment is 8, rather than 1. + // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) + private readonly ulong _00; + private readonly ulong _01; + + /// Gets a new with all elements initialized to zero. + /// The type of the current instance () is not supported. + public static Vector128 Zero + { + get + { + ThrowIfUnsupportedType(); + return default; + } + } + + internal unsafe string DisplayString + { + get + { + if (IsSupported) + { + var items = new T[ElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); + return $"({string.Join(", ", items)})"; + } + else + { + return SR.NotSupported_Type; + } + } + } + + internal static int ElementCount + { + get + { + ThrowIfUnsupportedType(); + return Vector128.Size / Unsafe.SizeOf(); + } + } + + internal static bool IsSupported + { + get + { + return (typeof(T) == typeof(byte)) || + (typeof(T) == typeof(sbyte)) || + (typeof(T) == typeof(short)) || + (typeof(T) == typeof(ushort)) || + (typeof(T) == typeof(int)) || + (typeof(T) == typeof(uint)) || + (typeof(T) == typeof(long)) || + (typeof(T) == typeof(ulong)) || + (typeof(T) == typeof(float)) || + (typeof(T) == typeof(double)); + } + } + + internal static void ThrowIfUnsupportedType() + { + if (!IsSupported) + { + throw new NotSupportedException(SR.Arg_TypeNotSupported); + } + } + + /// Reinterprets the current instance as a new . + /// The type of the vector the current instance should be reinterpreted as. + /// The current instance reinterpreted as a new . + /// The type of the current instance () or the type of the target () is not supported. + public Vector128 As() where U : struct + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + return Unsafe.As, Vector128>(ref Unsafe.AsRef(in this)); + } + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsDouble() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsInt64() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector128 AsSByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector128 AsSingle() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector128 AsUInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector128 AsUInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector128 AsUInt64() => As(); + + /// Gets the element at the specified index. + /// The index of the element to get. + /// The value of the element at . + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public T GetElement(int index) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + ref T e0 = ref Unsafe.As, T>(ref Unsafe.AsRef(in this)); + return Unsafe.Add(ref e0, index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the current instance. + /// The index of the element to set. + /// The value to set the value to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public Vector128 WithElement(int index, T value) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + Vector128 result = this; + ref T e0 = ref Unsafe.As, T>(ref result); + Unsafe.Add(ref e0, index) = value; + return result; + } + + /// Gets the value of the lower 64-bits as a new . + /// The value of the lower 64-bits as a new . + /// The type of the current instance () is not supported. + public Vector64 GetLower() + { + ThrowIfUnsupportedType(); + Vector64.ThrowIfUnsupportedType(); + return Unsafe.As, Vector64>(ref Unsafe.AsRef(in this)); + } + + /// Creates a new with the lower 64-bits set to the specified value and the upper 64-bits set to the same value as that in the current instance. + /// The value of the lower 64-bits as a . + /// A new with the lower 64-bits set to the specified value and the upper 64-bits set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + public Vector128 WithLower(Vector64 value) + { + ThrowIfUnsupportedType(); + Vector64.ThrowIfUnsupportedType(); + + Vector128 result = this; + Unsafe.As, Vector64>(ref result) = value; + return result; + } + + /// Gets the value of the upper 64-bits as a new . + /// The value of the upper 64-bits as a new . + /// The type of the current instance () is not supported. + public Vector64 GetUpper() + { + ThrowIfUnsupportedType(); + Vector64.ThrowIfUnsupportedType(); + + ref Vector64 lower = ref Unsafe.As, Vector64>(ref Unsafe.AsRef(in this)); + return Unsafe.Add(ref lower, 1); + } + + /// Creates a new with the upper 64-bits set to the specified value and the upper 64-bits set to the same value as that in the current instance. + /// The value of the upper 64-bits as a . + /// A new with the upper 64-bits set to the specified value and the upper 64-bits set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + public Vector128 WithUpper(Vector64 value) + { + ThrowIfUnsupportedType(); + Vector64.ThrowIfUnsupportedType(); + + Vector128 result = this; + ref Vector64 lower = ref Unsafe.As, Vector64>(ref result); + Unsafe.Add(ref lower, 1) = value; + return result; + } + + /// Converts the current instance to a scalar containing the value of the first element. + /// A scalar containing the value of the first element. + /// The type of the current instance () is not supported. + public T ToScalar() + { + ThrowIfUnsupportedType(); + return Unsafe.As, T>(ref Unsafe.AsRef(in this)); + } + + /// Converts the current instance to a new with the lower 128-bits set to the value of the current instance and the upper 128-bits initialized to zero. + /// A new with the lower 128-bits set to the value of the current instance and the upper 128-bits initialized to zero. + /// The type of the current instance () is not supported. + public Vector256 ToVector256() + { + ThrowIfUnsupportedType(); + Vector256.ThrowIfUnsupportedType(); + + Vector256 result = Vector256.Zero; + Unsafe.As, Vector128>(ref result) = this; + return result; + } + + /// Converts the current instance to a new with the lower 128-bits set to the value of the current instance and the upper 128-bits left uninitialized. + /// A new with the lower 128-bits set to the value of the current instance and the upper 128-bits left uninitialized. + /// The type of the current instance () is not supported. + public unsafe Vector256 ToVector256Unsafe() + { + ThrowIfUnsupportedType(); + Vector256.ThrowIfUnsupportedType(); + + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc byte[Vector256.Size]; + Unsafe.AsRef>(pResult) = this; + return Unsafe.AsRef>(pResult); + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs index 48744bb5eab3..a4f4cd66d719 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256.cs @@ -2,45 +2,1038 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.Intrinsics { - [Intrinsic] - [DebuggerDisplay("{DisplayString,nq}")] - [DebuggerTypeProxy(typeof(Vector256DebugView<>))] - [StructLayout(LayoutKind.Sequential, Size = 32)] - public readonly struct Vector256 where T : struct + public static class Vector256 { - // These fields exist to ensure the alignment is 8, rather than 1. - // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) - private readonly ulong _00; - private readonly ulong _01; - private readonly ulong _02; - private readonly ulong _03; - - private unsafe string DisplayString - { - get - { - // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr` - // which are not actually supported by any current architecture. This shouldn't be - // an issue however and greatly simplifies the check - - if (typeof(T).IsPrimitive) - { - var items = new T[32 / Unsafe.SizeOf()]; - Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); - return $"({string.Join(", ", items)})"; - } - else - { - return SR.NotSupported_Type; - } - } + internal const int Size = 32; + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(byte value) + { + var pResult = stackalloc byte[32] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(double value) + { + var pResult = stackalloc double[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(short value) + { + var pResult = stackalloc short[16] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(int value) + { + var pResult = stackalloc int[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(long value) + { + var pResult = stackalloc long[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector256 Create(sbyte value) + { + var pResult = stackalloc sbyte[32] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector256 Create(float value) + { + var pResult = stackalloc float[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector256 Create(ushort value) + { + var pResult = stackalloc ushort[16] + { + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector256 Create(uint value) + { + var pResult = stackalloc uint[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector256 Create(ulong value) + { + var pResult = stackalloc ulong[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// The value that element 16 will be initialized to. + /// The value that element 17 will be initialized to. + /// The value that element 18 will be initialized to. + /// The value that element 19 will be initialized to. + /// The value that element 20 will be initialized to. + /// The value that element 21 will be initialized to. + /// The value that element 22 will be initialized to. + /// The value that element 23 will be initialized to. + /// The value that element 24 will be initialized to. + /// The value that element 25 will be initialized to. + /// The value that element 26 will be initialized to. + /// The value that element 27 will be initialized to. + /// The value that element 28 will be initialized to. + /// The value that element 29 will be initialized to. + /// The value that element 30 will be initialized to. + /// The value that element 31 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7, byte e8, byte e9, byte e10, byte e11, byte e12, byte e13, byte e14, byte e15, byte e16, byte e17, byte e18, byte e19, byte e20, byte e21, byte e22, byte e23, byte e24, byte e25, byte e26, byte e27, byte e28, byte e29, byte e30, byte e31) + { + var pResult = stackalloc byte[32] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + e16, + e17, + e18, + e19, + e20, + e21, + e22, + e23, + e24, + e25, + e26, + e27, + e28, + e29, + e30, + e31, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(double e0, double e1, double e2, double e3) + { + var pResult = stackalloc double[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(short e0, short e1, short e2, short e3, short e4, short e5, short e6, short e7, short e8, short e9, short e10, short e11, short e12, short e13, short e14, short e15) + { + var pResult = stackalloc short[16] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(int e0, int e1, int e2, int e3, int e4, int e5, int e6, int e7) + { + var pResult = stackalloc int[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(long e0, long e1, long e2, long e3) + { + var pResult = stackalloc long[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// The value that element 16 will be initialized to. + /// The value that element 17 will be initialized to. + /// The value that element 18 will be initialized to. + /// The value that element 19 will be initialized to. + /// The value that element 20 will be initialized to. + /// The value that element 21 will be initialized to. + /// The value that element 22 will be initialized to. + /// The value that element 23 will be initialized to. + /// The value that element 24 will be initialized to. + /// The value that element 25 will be initialized to. + /// The value that element 26 will be initialized to. + /// The value that element 27 will be initialized to. + /// The value that element 28 will be initialized to. + /// The value that element 29 will be initialized to. + /// The value that element 30 will be initialized to. + /// The value that element 31 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector256 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7, sbyte e8, sbyte e9, sbyte e10, sbyte e11, sbyte e12, sbyte e13, sbyte e14, sbyte e15, sbyte e16, sbyte e17, sbyte e18, sbyte e19, sbyte e20, sbyte e21, sbyte e22, sbyte e23, sbyte e24, sbyte e25, sbyte e26, sbyte e27, sbyte e28, sbyte e29, sbyte e30, sbyte e31) + { + var pResult = stackalloc sbyte[32] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + e16, + e17, + e18, + e19, + e20, + e21, + e22, + e23, + e24, + e25, + e26, + e27, + e28, + e29, + e30, + e31, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector256 Create(float e0, float e1, float e2, float e3, float e4, float e5, float e6, float e7) + { + var pResult = stackalloc float[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// The value that element 8 will be initialized to. + /// The value that element 9 will be initialized to. + /// The value that element 10 will be initialized to. + /// The value that element 11 will be initialized to. + /// The value that element 12 will be initialized to. + /// The value that element 13 will be initialized to. + /// The value that element 14 will be initialized to. + /// The value that element 15 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector256 Create(ushort e0, ushort e1, ushort e2, ushort e3, ushort e4, ushort e5, ushort e6, ushort e7, ushort e8, ushort e9, ushort e10, ushort e11, ushort e12, ushort e13, ushort e14, ushort e15) + { + var pResult = stackalloc ushort[16] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + e8, + e9, + e10, + e11, + e12, + e13, + e14, + e15, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector256 Create(uint e0, uint e1, uint e2, uint e3, uint e4, uint e5, uint e6, uint e7) + { + var pResult = stackalloc uint[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector256 Create(ulong e0, ulong e1, ulong e2, ulong e3) + { + var pResult = stackalloc ulong[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance from two instances. + /// The value that the lower 128-bits will be initialized to. + /// The value that the upper 128-bits will be initialized to. + /// A new initialized from and . + [CLSCompliant(false)] + public static unsafe Vector256 Create(Vector128 lower, Vector128 upper) + { + Vector256 result256 = Vector256.Zero; + + ref Vector128 result128 = ref Unsafe.As, Vector128>(ref result256); + result128 = lower; + Unsafe.Add(ref result128, 1) = upper; + + return result256; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(byte value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(double value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(short value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(int value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(long value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalar(sbyte value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector256 CreateScalar(float value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalar(ushort value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalar(uint value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalar(ulong value) + { + var result = Vector256.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(byte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc byte[32]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(double value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc double[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(short value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc short[16]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(int value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc int[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(long value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc long[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalarUnsafe(sbyte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc sbyte[32]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector256 CreateScalarUnsafe(float value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc float[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalarUnsafe(ushort value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc ushort[16]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalarUnsafe(uint value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc uint[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector256 CreateScalarUnsafe(ulong value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc ulong[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView_1.cs similarity index 100% rename from src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView.cs rename to src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256DebugView_1.cs diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs new file mode 100644 index 000000000000..cd49d4832fb6 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector256_1.cs @@ -0,0 +1,251 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal.Runtime.CompilerServices; + +namespace System.Runtime.Intrinsics +{ + [Intrinsic] + [DebuggerDisplay("{DisplayString,nq}")] + [DebuggerTypeProxy(typeof(Vector256DebugView<>))] + [StructLayout(LayoutKind.Sequential, Size = Vector256.Size)] + public readonly struct Vector256 where T : struct + { + // These fields exist to ensure the alignment is 8, rather than 1. + // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) + private readonly ulong _00; + private readonly ulong _01; + private readonly ulong _02; + private readonly ulong _03; + + /// Gets a new with all elements initialized to zero. + /// The type of the current instance () is not supported. + public static Vector256 Zero + { + get + { + ThrowIfUnsupportedType(); + return default; + } + } + + internal unsafe string DisplayString + { + get + { + if (IsSupported) + { + var items = new T[ElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); + return $"({string.Join(", ", items)})"; + } + else + { + return SR.NotSupported_Type; + } + } + } + + internal static int ElementCount + { + get + { + ThrowIfUnsupportedType(); + return Vector256.Size / Unsafe.SizeOf(); + } + } + + internal static bool IsSupported + { + get + { + return (typeof(T) == typeof(byte)) || + (typeof(T) == typeof(sbyte)) || + (typeof(T) == typeof(short)) || + (typeof(T) == typeof(ushort)) || + (typeof(T) == typeof(int)) || + (typeof(T) == typeof(uint)) || + (typeof(T) == typeof(long)) || + (typeof(T) == typeof(ulong)) || + (typeof(T) == typeof(float)) || + (typeof(T) == typeof(double)); + } + } + + internal static void ThrowIfUnsupportedType() + { + if (!IsSupported) + { + throw new NotSupportedException(SR.Arg_TypeNotSupported); + } + } + + /// Reinterprets the current instance as a new . + /// The type of the vector the current instance should be reinterpreted as. + /// The current instance reinterpreted as a new . + /// The type of the current instance () or the type of the target () is not supported. + public Vector256 As() where U : struct + { + ThrowIfUnsupportedType(); + Vector256.ThrowIfUnsupportedType(); + return Unsafe.As, Vector256>(ref Unsafe.AsRef(in this)); + } + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsDouble() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsInt64() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector256 AsSByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector256 AsSingle() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector256 AsUInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector256 AsUInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector256 AsUInt64() => As(); + + /// Gets the element at the specified index. + /// The index of the element to get. + /// The value of the element at . + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public T GetElement(int index) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + ref T e0 = ref Unsafe.As, T>(ref Unsafe.AsRef(in this)); + return Unsafe.Add(ref e0, index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the current instance. + /// The index of the element to set. + /// The value to set the value to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public Vector256 WithElement(int index, T value) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + Vector256 result = this; + ref T e0 = ref Unsafe.As, T>(ref result); + Unsafe.Add(ref e0, index) = value; + return result; + } + + /// Gets the value of the lower 128-bits as a new . + /// The value of the lower 128-bits as a new . + /// The type of the current instance () is not supported. + public Vector128 GetLower() + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + return Unsafe.As, Vector128>(ref Unsafe.AsRef(in this)); + } + + /// Creates a new with the lower 128-bits set to the specified value and the lower 128-bits set to the same value as that in the current instance. + /// The value of the lower 128-bits as a . + /// A new with the lower 128-bits set to the specified value and the lower 128-bits set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + public Vector256 WithLower(Vector128 value) + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + + Vector256 result = this; + Unsafe.As, Vector128>(ref result) = value; + return result; + } + + /// Gets the value of the upper 128-bits as a new . + /// The value of the upper 128-bits as a new . + /// The type of the current instance () is not supported. + public Vector128 GetUpper() + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + + ref Vector128 lower = ref Unsafe.As, Vector128>(ref Unsafe.AsRef(in this)); + return Unsafe.Add(ref lower, 1); + } + + /// Creates a new with the upper 128-bits set to the specified value and the upper 128-bits set to the same value as that in the current instance. + /// The value of the upper 128-bits as a . + /// A new with the upper 128-bits set to the specified value and the upper 128-bits set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + public Vector256 WithUpper(Vector128 value) + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + + Vector256 result = this; + ref Vector128 lower = ref Unsafe.As, Vector128>(ref result); + Unsafe.Add(ref lower, 1) = value; + return result; + } + + /// Converts the current instance to a scalar containing the value of the first element. + /// A scalar containing the value of the first element. + /// The type of the current instance () is not supported. + public T ToScalar() + { + ThrowIfUnsupportedType(); + return Unsafe.As, T>(ref Unsafe.AsRef(in this)); + } + } +} diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs index 8ce90b9d0fa7..aa95c612c884 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64.cs @@ -2,42 +2,461 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; using Internal.Runtime.CompilerServices; namespace System.Runtime.Intrinsics { - [Intrinsic] - [DebuggerDisplay("{DisplayString,nq}")] - [DebuggerTypeProxy(typeof(Vector64DebugView<>))] - [StructLayout(LayoutKind.Sequential, Size = 8)] - public readonly struct Vector64 where T : struct + public static class Vector64 { - // These fields exist to ensure the alignment is 8, rather than 1. - // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) - private readonly ulong _00; - - private unsafe string DisplayString - { - get - { - // The IsPrimitive check ends up working for `bool`, `char`, `IntPtr`, and `UIntPtr` - // which are not actually supported by any current architecture. This shouldn't be - // an issue however and greatly simplifies the check - - if (typeof(T).IsPrimitive) - { - var items = new T[8 / Unsafe.SizeOf()]; - Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); - return $"({string.Join(", ", items)})"; - } - else - { - return SR.NotSupported_Type; - } - } + internal const int Size = 8; + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(byte value) + { + var pResult = stackalloc byte[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(double value) + { + return Unsafe.As>(ref value); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(short value) + { + var pResult = stackalloc short[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(int value) + { + var pResult = stackalloc int[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(long value) + { + return Unsafe.As>(ref value); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector64 Create(sbyte value) + { + var pResult = stackalloc sbyte[8] + { + value, + value, + value, + value, + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + public static unsafe Vector64 Create(float value) + { + var pResult = stackalloc float[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector64 Create(ushort value) + { + var pResult = stackalloc ushort[4] + { + value, + value, + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector64 Create(uint value) + { + var pResult = stackalloc uint[2] + { + value, + value, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with all elements initialized to the specified value. + /// The value that all elements will be initialized to. + /// A new with all elements initialized to . + [CLSCompliant(false)] + public static unsafe Vector64 Create(ulong value) + { + return Unsafe.As>(ref value); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector64 Create(byte e0, byte e1, byte e2, byte e3, byte e4, byte e5, byte e6, byte e7) + { + var pResult = stackalloc byte[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector64 Create(short e0, short e1, short e2, short e3) + { + var pResult = stackalloc short[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector64 Create(int e0, int e1) + { + var pResult = stackalloc int[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// The value that element 4 will be initialized to. + /// The value that element 5 will be initialized to. + /// The value that element 6 will be initialized to. + /// The value that element 7 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector64 Create(sbyte e0, sbyte e1, sbyte e2, sbyte e3, sbyte e4, sbyte e5, sbyte e6, sbyte e7) + { + var pResult = stackalloc sbyte[8] + { + e0, + e1, + e2, + e3, + e4, + e5, + e6, + e7, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + public static unsafe Vector64 Create(float e0, float e1) + { + var pResult = stackalloc float[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// The value that element 2 will be initialized to. + /// The value that element 3 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector64 Create(ushort e0, ushort e1, ushort e2, ushort e3) + { + var pResult = stackalloc ushort[4] + { + e0, + e1, + e2, + e3, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with each element initialized to the corresponding specified value. + /// The value that element 0 will be initialized to. + /// The value that element 1 will be initialized to. + /// A new with each element initialized to corresponding specified value. + [CLSCompliant(false)] + public static unsafe Vector64 Create(uint e0, uint e1) + { + var pResult = stackalloc uint[2] + { + e0, + e1, + }; + + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector64 CreateScalar(byte value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector64 CreateScalar(short value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector64 CreateScalar(int value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalar(sbyte value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + public static unsafe Vector64 CreateScalar(float value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalar(ushort value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements initialized to zero. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements initialized to zero. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalar(uint value) + { + var result = Vector64.Zero; + Unsafe.WriteUnaligned(ref Unsafe.As, byte>(ref result), value); + return result; + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector64 CreateScalarUnsafe(byte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc byte[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector64 CreateScalarUnsafe(short value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc short[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector64 CreateScalarUnsafe(int value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc int[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalarUnsafe(sbyte value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc sbyte[8]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + public static unsafe Vector64 CreateScalarUnsafe(float value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc float[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalarUnsafe(ushort value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc ushort[4]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); + } + + /// Creates a new instance with the first element initialized to the specified value and the remaining elements left uninitialized. + /// The value that element 0 will be initialized to. + /// A new instance with the first element initialized to and the remaining elements left uninitialized. + [CLSCompliant(false)] + public static unsafe Vector64 CreateScalarUnsafe(uint value) + { + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc uint[2]; + pResult[0] = value; + return Unsafe.AsRef>(pResult); } } } diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView_1.cs similarity index 100% rename from src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView.cs rename to src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64DebugView_1.cs diff --git a/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs new file mode 100644 index 000000000000..da9d0d20bd79 --- /dev/null +++ b/src/System.Private.CoreLib/shared/System/Runtime/Intrinsics/Vector64_1.cs @@ -0,0 +1,226 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Internal.Runtime.CompilerServices; + +namespace System.Runtime.Intrinsics +{ + [Intrinsic] + [DebuggerDisplay("{DisplayString,nq}")] + [DebuggerTypeProxy(typeof(Vector64DebugView<>))] + [StructLayout(LayoutKind.Sequential, Size = Vector64.Size)] + public readonly struct Vector64 where T : struct + { + // These fields exist to ensure the alignment is 8, rather than 1. + // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694) + private readonly ulong _00; + + /// Gets a new with all elements initialized to zero. + /// The type of the current instance () is not supported. + public static Vector64 Zero + { + get + { + ThrowIfUnsupportedType(); + return default; + } + } + + internal unsafe string DisplayString + { + get + { + if (IsSupported) + { + var items = new T[ElementCount]; + Unsafe.WriteUnaligned(ref Unsafe.As(ref items[0]), this); + return $"({string.Join(", ", items)})"; + } + else + { + return SR.NotSupported_Type; + } + } + } + + internal static int ElementCount + { + get + { + ThrowIfUnsupportedType(); + return Vector64.Size / Unsafe.SizeOf(); + } + } + + internal static bool IsSupported + { + get + { + return (typeof(T) == typeof(byte)) || + (typeof(T) == typeof(sbyte)) || + (typeof(T) == typeof(short)) || + (typeof(T) == typeof(ushort)) || + (typeof(T) == typeof(int)) || + (typeof(T) == typeof(uint)) || + (typeof(T) == typeof(long)) || + (typeof(T) == typeof(ulong)) || + (typeof(T) == typeof(float)) || + (typeof(T) == typeof(double)); + } + } + + internal static void ThrowIfUnsupportedType() + { + if (!IsSupported) + { + throw new NotSupportedException(SR.Arg_TypeNotSupported); + } + } + + /// Reinterprets the current instance as a new . + /// The type of the vector the current instance should be reinterpreted as. + /// The current instance reinterpreted as a new . + /// The type of the current instance () or the type of the target () is not supported. + public Vector64 As() where U : struct + { + ThrowIfUnsupportedType(); + Vector64.ThrowIfUnsupportedType(); + return Unsafe.As, Vector64>(ref Unsafe.AsRef(in this)); + } + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsDouble() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsInt64() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector64 AsSByte() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + public Vector64 AsSingle() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector64 AsUInt16() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector64 AsUInt32() => As(); + + /// Reinterprets the current instance as a new . + /// The current instance reinterpreted as a new . + /// The type of the current instance () is not supported. + [CLSCompliant(false)] + public Vector64 AsUInt64() => As(); + + /// Gets the element at the specified index. + /// The index of the element to get. + /// The value of the element at . + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public T GetElement(int index) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + ref T e0 = ref Unsafe.As, T>(ref Unsafe.AsRef(in this)); + return Unsafe.Add(ref e0, index); + } + + /// Creates a new with the element at the specified index set to the specified value and the remaining elements set to the same value as that in the current instance. + /// The index of the element to set. + /// The value to set the value to. + /// A with the value of the element at set to and the remaining elements set to the same value as that in the current instance. + /// The type of the current instance () is not supported. + /// was less than zero or greater than the number of elements. + public Vector64 WithElement(int index, T value) + { + ThrowIfUnsupportedType(); + + if ((uint)(index) >= (uint)(ElementCount)) + { + throw new ArgumentOutOfRangeException(nameof(index)); + } + + Vector64 result = this; + ref T e0 = ref Unsafe.As, T>(ref result); + Unsafe.Add(ref e0, index) = value; + return result; + } + + /// Converts the current instance to a scalar containing the value of the first element. + /// A scalar containing the value of the first element. + /// The type of the current instance () is not supported. + public T ToScalar() + { + ThrowIfUnsupportedType(); + return Unsafe.As, T>(ref Unsafe.AsRef(in this)); + } + + /// Converts the current instance to a new with the lower 64-bits set to the value of the current instance and the upper 64-bits initialized to zero. + /// A new with the lower 64-bits set to the value of the current instance and the upper 64-bits initialized to zero. + /// The type of the current instance () is not supported. + public Vector128 ToVector128() + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + + Vector128 result = Vector128.Zero; + Unsafe.As, Vector64>(ref result) = this; + return result; + } + + /// Converts the current instance to a new with the lower 64-bits set to the value of the current instance and the upper 64-bits left uninitialized. + /// A new with the lower 64-bits set to the value of the current instance and the upper 64-bits initialized to zero. + /// The type of the current instance () is not supported. + public unsafe Vector128 ToVector128Unsafe() + { + ThrowIfUnsupportedType(); + Vector128.ThrowIfUnsupportedType(); + + // This relies on us stripping the "init" flag from the ".locals" + // declaration to let the upper bits be uninitialized. + + var pResult = stackalloc byte[Vector128.Size]; + Unsafe.AsRef>(pResult) = this; + return Unsafe.AsRef>(pResult); + } + } +}