1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
5 using System.Diagnostics;
6 using System.Globalization;
7 using System.Runtime.CompilerServices;
8 using System.Runtime.InteropServices;
10 using Internal.Runtime.CompilerServices;
12 namespace System.Runtime.Intrinsics
15 [DebuggerDisplay("{DisplayString,nq}")]
16 [DebuggerTypeProxy(typeof(Vector256DebugView<>))]
17 [StructLayout(LayoutKind.Sequential, Size = Vector256.Size)]
18 public readonly struct Vector256<T> : IEquatable<Vector256<T>>, IFormattable
21 // These fields exist to ensure the alignment is 8, rather than 1.
22 // This also allows the debug view to work https://github.com/dotnet/coreclr/issues/15694)
23 private readonly ulong _00;
24 private readonly ulong _01;
25 private readonly ulong _02;
26 private readonly ulong _03;
28 /// <summary>Gets the number of <typeparamref name="T" /> that are in a <see cref="Vector256{T}" />.</summary>
29 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
30 public static int Count
34 ThrowIfUnsupportedType();
35 return Vector256.Size / Unsafe.SizeOf<T>();
39 /// <summary>Gets a new <see cref="Vector256{T}" /> with all elements initialized to zero.</summary>
40 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
41 public static Vector256<T> Zero
46 ThrowIfUnsupportedType();
51 internal unsafe string DisplayString
61 return SR.NotSupported_Type;
66 internal static bool IsSupported
68 [MethodImpl(MethodImplOptions.AggressiveInlining)]
71 return (typeof(T) == typeof(byte)) ||
72 (typeof(T) == typeof(sbyte)) ||
73 (typeof(T) == typeof(short)) ||
74 (typeof(T) == typeof(ushort)) ||
75 (typeof(T) == typeof(int)) ||
76 (typeof(T) == typeof(uint)) ||
77 (typeof(T) == typeof(long)) ||
78 (typeof(T) == typeof(ulong)) ||
79 (typeof(T) == typeof(float)) ||
80 (typeof(T) == typeof(double));
84 [MethodImpl(MethodImplOptions.AggressiveInlining)]
85 internal static void ThrowIfUnsupportedType()
89 throw new NotSupportedException(SR.Arg_TypeNotSupported);
93 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{U}" />.</summary>
94 /// <typeparam name="U">The type of the vector the current instance should be reinterpreted as.</typeparam>
95 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{U}" />.</returns>
96 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) or the type of the target (<typeparamref name="U" />) is not supported.</exception>
98 [MethodImpl(MethodImplOptions.AggressiveInlining)]
99 public Vector256<U> As<U>() where U : struct
101 ThrowIfUnsupportedType();
102 Vector256<U>.ThrowIfUnsupportedType();
103 return Unsafe.As<Vector256<T>, Vector256<U>>(ref Unsafe.AsRef(in this));
106 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{byte}" />.</summary>
107 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{byte}" />.</returns>
108 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
110 public Vector256<byte> AsByte() => As<byte>();
112 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{double}" />.</summary>
113 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{double}" />.</returns>
114 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
116 public Vector256<double> AsDouble() => As<double>();
118 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{short}" />.</summary>
119 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{short}" />.</returns>
120 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
122 public Vector256<short> AsInt16() => As<short>();
124 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{int}" />.</summary>
125 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{int}" />.</returns>
126 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
128 public Vector256<int> AsInt32() => As<int>();
130 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{long}" />.</summary>
131 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{long}" />.</returns>
132 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
134 public Vector256<long> AsInt64() => As<long>();
136 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{sbyte}" />.</summary>
137 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{sbyte}" />.</returns>
138 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
140 [CLSCompliant(false)]
141 public Vector256<sbyte> AsSByte() => As<sbyte>();
143 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{float}" />.</summary>
144 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{float}" />.</returns>
145 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
147 public Vector256<float> AsSingle() => As<float>();
149 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{ushort}" />.</summary>
150 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{ushort}" />.</returns>
151 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
153 [CLSCompliant(false)]
154 public Vector256<ushort> AsUInt16() => As<ushort>();
156 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{uint}" />.</summary>
157 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{uint}" />.</returns>
158 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
160 [CLSCompliant(false)]
161 public Vector256<uint> AsUInt32() => As<uint>();
163 /// <summary>Reinterprets the current instance as a new <see cref="Vector256{ulong}" />.</summary>
164 /// <returns>The current instance reinterpreted as a new <see cref="Vector256{ulong}" />.</returns>
165 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
167 [CLSCompliant(false)]
168 public Vector256<ulong> AsUInt64() => As<ulong>();
170 /// <summary>Determines whether the specified <see cref="Vector256{T}" /> is equal to the current instance.</summary>
171 /// <param name="other">The <see cref="Vector256{T}" /> to compare with the current instance.</param>
172 /// <returns><c>true</c> if <paramref name="other" /> is equal to the current instance; otherwise, <c>false</c>.</returns>
173 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
174 public bool Equals(Vector256<T> other)
176 ThrowIfUnsupportedType();
178 for (int i = 0; i < Count; i++)
180 if (!((IEquatable<T>)(GetElement(i))).Equals(other.GetElement(i)))
189 /// <summary>Determines whether the specified object is equal to the current instance.</summary>
190 /// <param name="obj">The object to compare with the current instance.</param>
191 /// <returns><c>true</c> if <paramref name="obj" /> is a <see cref="Vector256{T}" /> and is equal to the current instance; otherwise, <c>false</c>.</returns>
192 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
193 public override bool Equals(object obj)
195 return (obj is Vector256<T>) && Equals((Vector256<T>)(obj));
198 /// <summary>Gets the element at the specified index.</summary>
199 /// <param name="index">The index of the element to get.</param>
200 /// <returns>The value of the element at <paramref name="index" />.</returns>
201 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
202 /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
203 public T GetElement(int index)
205 ThrowIfUnsupportedType();
207 if ((uint)(index) >= (uint)(Count))
209 throw new ArgumentOutOfRangeException(nameof(index));
212 ref T e0 = ref Unsafe.As<Vector256<T>, T>(ref Unsafe.AsRef(in this));
213 return Unsafe.Add(ref e0, index);
216 /// <summary>Creates a new <see cref="Vector256{T}" /> 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.</summary>
217 /// <param name="index">The index of the element to set.</param>
218 /// <param name="value">The value to set the value to.</param>
219 /// <returns>A <see cref="Vector256{T}" /> with the value of the element at <paramref name="index" /> set to <paramref name="value" /> and the remaining elements set to the same value as that in the current instance.</returns>
220 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
221 /// <exception cref="ArgumentOutOfRangeException"><paramref name="index" /> was less than zero or greater than the number of elements.</exception>
222 public Vector256<T> WithElement(int index, T value)
224 ThrowIfUnsupportedType();
226 if ((uint)(index) >= (uint)(Count))
228 throw new ArgumentOutOfRangeException(nameof(index));
231 Vector256<T> result = this;
232 ref T e0 = ref Unsafe.As<Vector256<T>, T>(ref result);
233 Unsafe.Add(ref e0, index) = value;
237 /// <summary>Gets the hash code for the instance.</summary>
238 /// <returns>The hash code for the instance.</returns>
239 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
240 public override int GetHashCode()
242 ThrowIfUnsupportedType();
246 for (int i = 0; i < Count; i++)
248 hashCode = HashCode.Combine(hashCode, GetElement(i).GetHashCode());
254 /// <summary>Gets the value of the lower 128-bits as a new <see cref="Vector128{T}" />.</summary>
255 /// <returns>The value of the lower 128-bits as a new <see cref="Vector128{T}" />.</returns>
256 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
257 public Vector128<T> GetLower()
259 ThrowIfUnsupportedType();
260 Vector128<T>.ThrowIfUnsupportedType();
261 return Unsafe.As<Vector256<T>, Vector128<T>>(ref Unsafe.AsRef(in this));
264 /// <summary>Creates a new <see cref="Vector256{T}" /> 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.</summary>
265 /// <param name="value">The value of the lower 128-bits as a <see cref="Vector128{T}" />.</param>
266 /// <returns>A new <see cref="Vector256{T}" /> 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.</returns>
267 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
268 public Vector256<T> WithLower(Vector128<T> value)
270 ThrowIfUnsupportedType();
271 Vector128<T>.ThrowIfUnsupportedType();
273 Vector256<T> result = this;
274 Unsafe.As<Vector256<T>, Vector128<T>>(ref result) = value;
278 /// <summary>Gets the value of the upper 128-bits as a new <see cref="Vector128{T}" />.</summary>
279 /// <returns>The value of the upper 128-bits as a new <see cref="Vector128{T}" />.</returns>
280 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
281 public Vector128<T> GetUpper()
283 ThrowIfUnsupportedType();
284 Vector128<T>.ThrowIfUnsupportedType();
286 ref Vector128<T> lower = ref Unsafe.As<Vector256<T>, Vector128<T>>(ref Unsafe.AsRef(in this));
287 return Unsafe.Add(ref lower, 1);
290 /// <summary>Creates a new <see cref="Vector256{T}" /> 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.</summary>
291 /// <param name="value">The value of the upper 128-bits as a <see cref="Vector128{T}" />.</param>
292 /// <returns>A new <see cref="Vector256{T}" /> 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.</returns>
293 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
294 public Vector256<T> WithUpper(Vector128<T> value)
296 ThrowIfUnsupportedType();
297 Vector128<T>.ThrowIfUnsupportedType();
299 Vector256<T> result = this;
300 ref Vector128<T> lower = ref Unsafe.As<Vector256<T>, Vector128<T>>(ref result);
301 Unsafe.Add(ref lower, 1) = value;
305 /// <summary>Converts the current instance to a scalar containing the value of the first element.</summary>
306 /// <returns>A scalar <typeparamref name="T" /> containing the value of the first element.</returns>
307 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
310 ThrowIfUnsupportedType();
311 return Unsafe.As<Vector256<T>, T>(ref Unsafe.AsRef(in this));
314 /// <summary>Converts the current instance to an equivalent string representation.</summary>
315 /// <returns>An equivalent string representation of the current instance.</returns>
316 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
317 public override string ToString()
319 return ToString("G");
322 /// <summary>Converts the current instance to an equivalent string representation using the specified format.</summary>
323 /// <param name="format">The format specifier used to format the individual elements of the current instance.</param>
324 /// <returns>An equivalent string representation of the current instance.</returns>
325 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
326 public string ToString(string format)
328 return ToString(format, CultureInfo.CurrentCulture);
331 /// <summary>Converts the current instance to an equivalent string representation using the specified format.</summary>
332 /// <param name="format">The format specifier used to format the individual elements of the current instance.</param>
333 /// <param name="formatProvider">The format provider used to format the individual elements of the current instance.</param>
334 /// <returns>An equivalent string representation of the current instance.</returns>
335 /// <exception cref="NotSupportedException">The type of the current instance (<typeparamref name="T" />) is not supported.</exception>
336 public string ToString(string format, IFormatProvider formatProvider)
338 ThrowIfUnsupportedType();
340 string separator = NumberFormatInfo.GetInstance(formatProvider).NumberGroupSeparator;
341 int lastElement = Count - 1;
343 var sb = StringBuilderCache.Acquire();
346 for (int i = 0; i < lastElement; i++)
348 sb.Append(((IFormattable)(GetElement(i))).ToString(format, formatProvider));
349 sb.Append(separator);
352 sb.Append(((IFormattable)(GetElement(lastElement))).ToString(format, formatProvider));
355 return StringBuilderCache.GetStringAndRelease(sb);