Explode generic Intel hardware intrinsic on all the supported types
[platform/upstream/coreclr.git] / tests / src / JIT / HardwareIntrinsics / X86 / Avx / Permute2x128.Double.2.cs
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.
4
5 /******************************************************************************
6  * This file is auto-generated from a template file by the GenerateTests.csx  *
7  * script in tests\src\JIT\HardwareIntrinsics\X86\Shared. In order to make    *
8  * changes, please update the corresponding template and run according to the *
9  * directions listed in the file.                                             *
10  ******************************************************************************/
11
12 using System;
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Runtime.Intrinsics;
16 using System.Runtime.Intrinsics.X86;
17
18 namespace JIT.HardwareIntrinsics.X86
19 {
20     public static partial class Program
21     {
22         private static void Permute2x128Double2()
23         {
24             var test = new SimpleBinaryOpTest__Permute2x128Double2();
25
26             if (test.IsSupported)
27             {
28                 // Validates basic functionality works, using Unsafe.Read
29                 test.RunBasicScenario_UnsafeRead();
30
31                 if (Avx.IsSupported)
32                 {
33                     // Validates basic functionality works, using Load
34                     test.RunBasicScenario_Load();
35
36                     // Validates basic functionality works, using LoadAligned
37                     test.RunBasicScenario_LoadAligned();
38                 }
39
40                 // Validates calling via reflection works, using Unsafe.Read
41                 test.RunReflectionScenario_UnsafeRead();
42
43                 if (Avx.IsSupported)
44                 {
45                     // Validates calling via reflection works, using Load
46                     test.RunReflectionScenario_Load();
47
48                     // Validates calling via reflection works, using LoadAligned
49                     test.RunReflectionScenario_LoadAligned();
50                 }
51
52                 // Validates passing a static member works
53                 test.RunClsVarScenario();
54
55                 // Validates passing a local works, using Unsafe.Read
56                 test.RunLclVarScenario_UnsafeRead();
57
58                 if (Avx.IsSupported)
59                 {
60                     // Validates passing a local works, using Load
61                     test.RunLclVarScenario_Load();
62
63                     // Validates passing a local works, using LoadAligned
64                     test.RunLclVarScenario_LoadAligned();
65                 }
66
67                 // Validates passing the field of a local works
68                 test.RunLclFldScenario();
69
70                 // Validates passing an instance member works
71                 test.RunFldScenario();
72             }
73             else
74             {
75                 // Validates we throw on unsupported hardware
76                 test.RunUnsupportedScenario();
77             }
78
79             if (!test.Succeeded)
80             {
81                 throw new Exception("One or more scenarios did not complete as expected.");
82             }
83         }
84     }
85
86     public sealed unsafe class SimpleBinaryOpTest__Permute2x128Double2
87     {
88         private const int VectorSize = 32;
89
90         private const int Op1ElementCount = VectorSize / sizeof(Double);
91         private const int Op2ElementCount = VectorSize / sizeof(Double);
92         private const int RetElementCount = VectorSize / sizeof(Double);
93
94         private static Double[] _data1 = new Double[Op1ElementCount];
95         private static Double[] _data2 = new Double[Op2ElementCount];
96
97         private static Vector256<Double> _clsVar1;
98         private static Vector256<Double> _clsVar2;
99
100         private Vector256<Double> _fld1;
101         private Vector256<Double> _fld2;
102
103         private SimpleBinaryOpTest__DataTable<Double, Double, Double> _dataTable;
104
105         static SimpleBinaryOpTest__Permute2x128Double2()
106         {
107             var random = new Random();
108
109             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
110             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
111             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
112             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
113         }
114
115         public SimpleBinaryOpTest__Permute2x128Double2()
116         {
117             Succeeded = true;
118
119             var random = new Random();
120
121             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
122             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), VectorSize);
123             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
124             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), VectorSize);
125
126             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
127             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
128             _dataTable = new SimpleBinaryOpTest__DataTable<Double, Double, Double>(_data1, _data2, new Double[RetElementCount], VectorSize);
129         }
130
131         public bool IsSupported => Avx.IsSupported;
132
133         public bool Succeeded { get; set; }
134
135         public void RunBasicScenario_UnsafeRead()
136         {
137             var result = Avx.Permute2x128(
138                 Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
139                 Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr),
140                 2
141             );
142
143             Unsafe.Write(_dataTable.outArrayPtr, result);
144             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
145         }
146
147         public void RunBasicScenario_Load()
148         {
149             var result = Avx.Permute2x128(
150                 Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
151                 Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr)),
152                 2
153             );
154
155             Unsafe.Write(_dataTable.outArrayPtr, result);
156             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
157         }
158
159         public void RunBasicScenario_LoadAligned()
160         {
161             var result = Avx.Permute2x128(
162                 Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
163                 Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr)),
164                 2
165             );
166
167             Unsafe.Write(_dataTable.outArrayPtr, result);
168             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
169         }
170
171         public void RunReflectionScenario_UnsafeRead()
172         {
173             var result = typeof(Avx).GetMethod(nameof(Avx.Permute2x128)).MakeGenericMethod( new Type[] { typeof(Double) })
174                                      .Invoke(null, new object[] {
175                                         Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr),
176                                         Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr),
177                                         (byte)2
178                                      });
179
180             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
181             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
182         }
183
184         public void RunReflectionScenario_Load()
185         {
186             var result = typeof(Avx).GetMethod(nameof(Avx.Permute2x128)).MakeGenericMethod( new Type[] { typeof(Double) })
187                                      .Invoke(null, new object[] {
188                                         Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr)),
189                                         Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr)),
190                                         (byte)2
191                                      });
192
193             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
194             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
195         }
196
197         public void RunReflectionScenario_LoadAligned()
198         {
199             var result = typeof(Avx).GetMethod(nameof(Avx.Permute2x128)).MakeGenericMethod( new Type[] { typeof(Double) })
200                                      .Invoke(null, new object[] {
201                                         Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr)),
202                                         Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr)),
203                                         (byte)2
204                                      });
205
206             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Double>)(result));
207             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
208         }
209
210         public void RunClsVarScenario()
211         {
212             var result = Avx.Permute2x128(
213                 _clsVar1,
214                 _clsVar2,
215                 2
216             );
217
218             Unsafe.Write(_dataTable.outArrayPtr, result);
219             ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
220         }
221
222         public void RunLclVarScenario_UnsafeRead()
223         {
224             var left = Unsafe.Read<Vector256<Double>>(_dataTable.inArray1Ptr);
225             var right = Unsafe.Read<Vector256<Double>>(_dataTable.inArray2Ptr);
226             var result = Avx.Permute2x128(left, right, 2);
227
228             Unsafe.Write(_dataTable.outArrayPtr, result);
229             ValidateResult(left, right, _dataTable.outArrayPtr);
230         }
231
232         public void RunLclVarScenario_Load()
233         {
234             var left = Avx.LoadVector256((Double*)(_dataTable.inArray1Ptr));
235             var right = Avx.LoadVector256((Double*)(_dataTable.inArray2Ptr));
236             var result = Avx.Permute2x128(left, right, 2);
237
238             Unsafe.Write(_dataTable.outArrayPtr, result);
239             ValidateResult(left, right, _dataTable.outArrayPtr);
240         }
241
242         public void RunLclVarScenario_LoadAligned()
243         {
244             var left = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray1Ptr));
245             var right = Avx.LoadAlignedVector256((Double*)(_dataTable.inArray2Ptr));
246             var result = Avx.Permute2x128(left, right, 2);
247
248             Unsafe.Write(_dataTable.outArrayPtr, result);
249             ValidateResult(left, right, _dataTable.outArrayPtr);
250         }
251
252         public void RunLclFldScenario()
253         {
254             var test = new SimpleBinaryOpTest__Permute2x128Double2();
255             var result = Avx.Permute2x128(test._fld1, test._fld2, 2);
256
257             Unsafe.Write(_dataTable.outArrayPtr, result);
258             ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
259         }
260
261         public void RunFldScenario()
262         {
263             var result = Avx.Permute2x128(_fld1, _fld2, 2);
264
265             Unsafe.Write(_dataTable.outArrayPtr, result);
266             ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
267         }
268
269         public void RunUnsupportedScenario()
270         {
271             Succeeded = false;
272
273             try
274             {
275                 RunBasicScenario_UnsafeRead();
276             }
277             catch (PlatformNotSupportedException)
278             {
279                 Succeeded = true;
280             }
281         }
282
283         private void ValidateResult(Vector256<Double> left, Vector256<Double> right, void* result, [CallerMemberName] string method = "")
284         {
285             Double[] inArray1 = new Double[Op1ElementCount];
286             Double[] inArray2 = new Double[Op2ElementCount];
287             Double[] outArray = new Double[RetElementCount];
288
289             Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), left);
290             Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), right);
291             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
292
293             ValidateResult(inArray1, inArray2, outArray, method);
294         }
295
296         private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "")
297         {
298             Double[] inArray1 = new Double[Op1ElementCount];
299             Double[] inArray2 = new Double[Op2ElementCount];
300             Double[] outArray = new Double[RetElementCount];
301
302             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), VectorSize);
303             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), VectorSize);
304             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), VectorSize);
305
306             ValidateResult(inArray1, inArray2, outArray, method);
307         }
308
309         private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
310         {
311             if (BitConverter.DoubleToInt64Bits(result[0]) != BitConverter.DoubleToInt64Bits(right[0]))
312             {
313                 Succeeded = false;
314             }
315             else
316             {
317                 for (var i = 1; i < RetElementCount; i++)
318                 {
319                     if (i > 1 ? (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(left[i - 2])) : (BitConverter.DoubleToInt64Bits(result[i]) != BitConverter.DoubleToInt64Bits(right[i])))
320                     {
321                         Succeeded = false;
322                         break;
323                     }
324                 }
325             }
326
327             if (!Succeeded)
328             {
329                 Console.WriteLine($"{nameof(Avx)}.{nameof(Avx.Permute2x128)}<Double>(Vector256<Double>.2, Vector256<Double>): {method} failed:");
330                 Console.WriteLine($"    left: ({string.Join(", ", left)})");
331                 Console.WriteLine($"   right: ({string.Join(", ", right)})");
332                 Console.WriteLine($"  result: ({string.Join(", ", result)})");
333                 Console.WriteLine();
334             }
335         }
336     }
337 }