Remove random.NextDouble() from JIT/HardwareIntrinsics tests (#18838)
[platform/upstream/coreclr.git] / tests / src / JIT / HardwareIntrinsics / X86 / Sse2 / MaxScalar.Double.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 MaxScalarDouble()
23         {
24             var test = new SimpleBinaryOpTest__MaxScalarDouble();
25
26             if (test.IsSupported)
27             {
28                 // Validates basic functionality works, using Unsafe.Read
29                 test.RunBasicScenario_UnsafeRead();
30
31                 if (Sse2.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 (Sse2.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 (Sse2.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 class works
68                 test.RunClassLclFldScenario();
69
70                 // Validates passing an instance member of a class works
71                 test.RunClassFldScenario();
72
73                 // Validates passing the field of a local struct works
74                 test.RunStructLclFldScenario();
75
76                 // Validates passing an instance member of a struct works
77                 test.RunStructFldScenario();
78             }
79             else
80             {
81                 // Validates we throw on unsupported hardware
82                 test.RunUnsupportedScenario();
83             }
84
85             if (!test.Succeeded)
86             {
87                 throw new Exception("One or more scenarios did not complete as expected.");
88             }
89         }
90     }
91
92     public sealed unsafe class SimpleBinaryOpTest__MaxScalarDouble
93     {
94         private struct TestStruct
95         {
96             public Vector128<Double> _fld1;
97             public Vector128<Double> _fld2;
98
99             public static TestStruct Create()
100             {
101                 var testStruct = new TestStruct();
102                 var random = new Random();
103
104                 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
105                 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
106                 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
107                 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
108
109                 return testStruct;
110             }
111
112             public void RunStructFldScenario(SimpleBinaryOpTest__MaxScalarDouble testClass)
113             {
114                 var result = Sse2.MaxScalar(_fld1, _fld2);
115
116                 Unsafe.Write(testClass._dataTable.outArrayPtr, result);
117                 testClass.ValidateResult(_fld1, _fld2, testClass._dataTable.outArrayPtr);
118             }
119         }
120
121         private static readonly int LargestVectorSize = 16;
122
123         private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
124         private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
125         private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
126
127         private static Double[] _data1 = new Double[Op1ElementCount];
128         private static Double[] _data2 = new Double[Op2ElementCount];
129
130         private static Vector128<Double> _clsVar1;
131         private static Vector128<Double> _clsVar2;
132
133         private Vector128<Double> _fld1;
134         private Vector128<Double> _fld2;
135
136         private SimpleBinaryOpTest__DataTable<Double, Double, Double> _dataTable;
137
138         static SimpleBinaryOpTest__MaxScalarDouble()
139         {
140             var random = new Random();
141
142             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
143             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
144             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
145             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
146         }
147
148         public SimpleBinaryOpTest__MaxScalarDouble()
149         {
150             Succeeded = true;
151
152             var random = new Random();
153
154             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
155             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
156             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
157             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
158
159             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetDouble(); }
160             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetDouble(); }
161             _dataTable = new SimpleBinaryOpTest__DataTable<Double, Double, Double>(_data1, _data2, new Double[RetElementCount], LargestVectorSize);
162         }
163
164         public bool IsSupported => Sse2.IsSupported;
165
166         public bool Succeeded { get; set; }
167
168         public void RunBasicScenario_UnsafeRead()
169         {
170             var result = Sse2.MaxScalar(
171                 Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
172                 Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
173             );
174
175             Unsafe.Write(_dataTable.outArrayPtr, result);
176             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
177         }
178
179         public void RunBasicScenario_Load()
180         {
181             var result = Sse2.MaxScalar(
182                 Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
183                 Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr))
184             );
185
186             Unsafe.Write(_dataTable.outArrayPtr, result);
187             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
188         }
189
190         public void RunBasicScenario_LoadAligned()
191         {
192             var result = Sse2.MaxScalar(
193                 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
194                 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr))
195             );
196
197             Unsafe.Write(_dataTable.outArrayPtr, result);
198             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
199         }
200
201         public void RunReflectionScenario_UnsafeRead()
202         {
203             var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
204                                      .Invoke(null, new object[] {
205                                         Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
206                                         Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr)
207                                      });
208
209             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
210             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
211         }
212
213         public void RunReflectionScenario_Load()
214         {
215             var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
216                                      .Invoke(null, new object[] {
217                                         Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
218                                         Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr))
219                                      });
220
221             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
222             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
223         }
224
225         public void RunReflectionScenario_LoadAligned()
226         {
227             var result = typeof(Sse2).GetMethod(nameof(Sse2.MaxScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>) })
228                                      .Invoke(null, new object[] {
229                                         Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
230                                         Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr))
231                                      });
232
233             Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
234             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.outArrayPtr);
235         }
236
237         public void RunClsVarScenario()
238         {
239             var result = Sse2.MaxScalar(
240                 _clsVar1,
241                 _clsVar2
242             );
243
244             Unsafe.Write(_dataTable.outArrayPtr, result);
245             ValidateResult(_clsVar1, _clsVar2, _dataTable.outArrayPtr);
246         }
247
248         public void RunLclVarScenario_UnsafeRead()
249         {
250             var left = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr);
251             var right = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
252             var result = Sse2.MaxScalar(left, right);
253
254             Unsafe.Write(_dataTable.outArrayPtr, result);
255             ValidateResult(left, right, _dataTable.outArrayPtr);
256         }
257
258         public void RunLclVarScenario_Load()
259         {
260             var left = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
261             var right = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr));
262             var result = Sse2.MaxScalar(left, right);
263
264             Unsafe.Write(_dataTable.outArrayPtr, result);
265             ValidateResult(left, right, _dataTable.outArrayPtr);
266         }
267
268         public void RunLclVarScenario_LoadAligned()
269         {
270             var left = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
271             var right = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr));
272             var result = Sse2.MaxScalar(left, right);
273
274             Unsafe.Write(_dataTable.outArrayPtr, result);
275             ValidateResult(left, right, _dataTable.outArrayPtr);
276         }
277
278         public void RunClassLclFldScenario()
279         {
280             var test = new SimpleBinaryOpTest__MaxScalarDouble();
281             var result = Sse2.MaxScalar(test._fld1, test._fld2);
282
283             Unsafe.Write(_dataTable.outArrayPtr, result);
284             ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
285         }
286
287         public void RunClassFldScenario()
288         {
289             var result = Sse2.MaxScalar(_fld1, _fld2);
290
291             Unsafe.Write(_dataTable.outArrayPtr, result);
292             ValidateResult(_fld1, _fld2, _dataTable.outArrayPtr);
293         }
294
295         public void RunStructLclFldScenario()
296         {
297             var test = TestStruct.Create();
298             var result = Sse2.MaxScalar(test._fld1, test._fld2);
299
300             Unsafe.Write(_dataTable.outArrayPtr, result);
301             ValidateResult(test._fld1, test._fld2, _dataTable.outArrayPtr);
302         }
303
304         public void RunStructFldScenario()
305         {
306             var test = TestStruct.Create();
307             test.RunStructFldScenario(this);
308         }
309
310         public void RunUnsupportedScenario()
311         {
312             Succeeded = false;
313
314             try
315             {
316                 RunBasicScenario_UnsafeRead();
317             }
318             catch (PlatformNotSupportedException)
319             {
320                 Succeeded = true;
321             }
322         }
323
324         private void ValidateResult(Vector128<Double> left, Vector128<Double> right, void* result, [CallerMemberName] string method = "")
325         {
326             Double[] inArray1 = new Double[Op1ElementCount];
327             Double[] inArray2 = new Double[Op2ElementCount];
328             Double[] outArray = new Double[RetElementCount];
329
330             Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), left);
331             Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), right);
332             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
333
334             ValidateResult(inArray1, inArray2, outArray, method);
335         }
336
337         private void ValidateResult(void* left, void* right, void* result, [CallerMemberName] string method = "")
338         {
339             Double[] inArray1 = new Double[Op1ElementCount];
340             Double[] inArray2 = new Double[Op2ElementCount];
341             Double[] outArray = new Double[RetElementCount];
342
343             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(left), (uint)Unsafe.SizeOf<Vector128<Double>>());
344             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(right), (uint)Unsafe.SizeOf<Vector128<Double>>());
345             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
346
347             ValidateResult(inArray1, inArray2, outArray, method);
348         }
349
350         private void ValidateResult(Double[] left, Double[] right, Double[] result, [CallerMemberName] string method = "")
351         {
352             if (BitConverter.DoubleToInt64Bits(Math.Max(left[0], right[0])) != BitConverter.DoubleToInt64Bits(result[0]))
353             {
354                 Succeeded = false;
355             }
356             else
357             {
358                 for (var i = 1; i < RetElementCount; i++)
359                 {
360                     if (BitConverter.DoubleToInt64Bits(left[i]) != BitConverter.DoubleToInt64Bits(result[i]))
361                     {
362                         Succeeded = false;
363                         break;
364                     }
365                 }
366             }
367
368             if (!Succeeded)
369             {
370                 Console.WriteLine($"{nameof(Sse2)}.{nameof(Sse2.MaxScalar)}<Double>(Vector128<Double>, Vector128<Double>): {method} failed:");
371                 Console.WriteLine($"    left: ({string.Join(", ", left)})");
372                 Console.WriteLine($"   right: ({string.Join(", ", right)})");
373                 Console.WriteLine($"  result: ({string.Join(", ", result)})");
374                 Console.WriteLine();
375             }
376         }
377     }
378 }