Remove random.NextDouble() from JIT/HardwareIntrinsics tests (#18838)
[platform/upstream/coreclr.git] / tests / src / JIT / HardwareIntrinsics / X86 / Fma_Vector256 / MultiplySubtractAdd.Single.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 MultiplySubtractAddSingle()
23         {
24             var test = new AlternatingTernaryOpTest__MultiplySubtractAddSingle();
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 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 AlternatingTernaryOpTest__MultiplySubtractAddSingle
93     {
94         private struct TestStruct
95         {
96             public Vector256<Single> _fld1;
97             public Vector256<Single> _fld2;
98             public Vector256<Single> _fld3;
99
100             public static TestStruct Create()
101             {
102                 var testStruct = new TestStruct();
103                 var random = new Random();
104
105                 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
106                 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
107                 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
108                 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
109                 for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = TestLibrary.Generator.GetSingle(); }
110                 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref testStruct._fld3), ref Unsafe.As<Single, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
111
112                 return testStruct;
113             }
114
115             public void RunStructFldScenario(AlternatingTernaryOpTest__MultiplySubtractAddSingle testClass)
116             {
117                 var result = Fma.MultiplySubtractAdd(_fld1, _fld2, _fld3);
118
119                 Unsafe.Write(testClass._dataTable.outArrayPtr, result);
120                 testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
121             }
122         }
123
124         private static readonly int LargestVectorSize = 32;
125
126         private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
127         private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
128         private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
129         private static readonly int RetElementCount = Unsafe.SizeOf<Vector256<Single>>() / sizeof(Single);
130
131         private static Single[] _data1 = new Single[Op1ElementCount];
132         private static Single[] _data2 = new Single[Op2ElementCount];
133         private static Single[] _data3 = new Single[Op3ElementCount];
134
135         private static Vector256<Single> _clsVar1;
136         private static Vector256<Single> _clsVar2;
137         private static Vector256<Single> _clsVar3;
138
139         private Vector256<Single> _fld1;
140         private Vector256<Single> _fld2;
141         private Vector256<Single> _fld3;
142
143         private AlternatingTernaryOpTest__DataTable<Single, Single, Single, Single> _dataTable;
144
145         static AlternatingTernaryOpTest__MultiplySubtractAddSingle()
146         {
147             var random = new Random();
148
149             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
150             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
151             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
152             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
153             for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = TestLibrary.Generator.GetSingle(); }
154             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _clsVar3), ref Unsafe.As<Single, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
155         }
156
157         public AlternatingTernaryOpTest__MultiplySubtractAddSingle()
158         {
159             Succeeded = true;
160
161             var random = new Random();
162
163             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
164             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld1), ref Unsafe.As<Single, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
165             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
166             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld2), ref Unsafe.As<Single, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
167             for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = TestLibrary.Generator.GetSingle(); }
168             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector256<Single>, byte>(ref _fld3), ref Unsafe.As<Single, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector256<Single>>());
169
170             for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = TestLibrary.Generator.GetSingle(); }
171             for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = TestLibrary.Generator.GetSingle(); }
172             for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = TestLibrary.Generator.GetSingle(); }
173             _dataTable = new AlternatingTernaryOpTest__DataTable<Single, Single, Single, Single>(_data1, _data2, _data3, new Single[RetElementCount], LargestVectorSize);
174         }
175
176         public bool IsSupported => Fma.IsSupported;
177
178         public bool Succeeded { get; set; }
179
180         public void RunBasicScenario_UnsafeRead()
181         {
182             var result = Fma.MultiplySubtractAdd(
183                 Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
184                 Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr),
185                 Unsafe.Read<Vector256<Single>>(_dataTable.inArray3Ptr)
186             );
187
188             Unsafe.Write(_dataTable.outArrayPtr, result);
189             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
190         }
191
192         public void RunBasicScenario_Load()
193         {
194             var result = Fma.MultiplySubtractAdd(
195                 Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
196                 Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr)),
197                 Avx.LoadVector256((Single*)(_dataTable.inArray3Ptr))
198             );
199
200             Unsafe.Write(_dataTable.outArrayPtr, result);
201             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
202         }
203
204         public void RunBasicScenario_LoadAligned()
205         {
206             var result = Fma.MultiplySubtractAdd(
207                 Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
208                 Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr)),
209                 Avx.LoadAlignedVector256((Single*)(_dataTable.inArray3Ptr))
210             );
211
212             Unsafe.Write(_dataTable.outArrayPtr, result);
213             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
214         }
215
216         public void RunReflectionScenario_UnsafeRead()
217         {
218             var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractAdd), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>), typeof(Vector256<Single>) })
219                                      .Invoke(null, new object[] {
220                                         Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr),
221                                         Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr),
222                                         Unsafe.Read<Vector256<Single>>(_dataTable.inArray3Ptr)
223                                      });
224
225             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
226             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
227         }
228
229         public void RunReflectionScenario_Load()
230         {
231             var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractAdd), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>), typeof(Vector256<Single>) })
232                                      .Invoke(null, new object[] {
233                                         Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr)),
234                                         Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr)),
235                                         Avx.LoadVector256((Single*)(_dataTable.inArray3Ptr))
236                                      });
237
238             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
239             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
240         }
241
242         public void RunReflectionScenario_LoadAligned()
243         {
244             var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractAdd), new Type[] { typeof(Vector256<Single>), typeof(Vector256<Single>), typeof(Vector256<Single>) })
245                                      .Invoke(null, new object[] {
246                                         Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr)),
247                                         Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr)),
248                                         Avx.LoadAlignedVector256((Single*)(_dataTable.inArray3Ptr))
249                                      });
250
251             Unsafe.Write(_dataTable.outArrayPtr, (Vector256<Single>)(result));
252             ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
253         }
254
255         public void RunClsVarScenario()
256         {
257             var result = Fma.MultiplySubtractAdd(
258                 _clsVar1,
259                 _clsVar2,
260                 _clsVar3
261             );
262
263             Unsafe.Write(_dataTable.outArrayPtr, result);
264             ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
265         }
266
267         public void RunLclVarScenario_UnsafeRead()
268         {
269             var firstOp = Unsafe.Read<Vector256<Single>>(_dataTable.inArray1Ptr);
270             var secondOp = Unsafe.Read<Vector256<Single>>(_dataTable.inArray2Ptr);
271             var thirdOp = Unsafe.Read<Vector256<Single>>(_dataTable.inArray3Ptr);
272             var result = Fma.MultiplySubtractAdd(firstOp, secondOp, thirdOp);
273
274             Unsafe.Write(_dataTable.outArrayPtr, result);
275             ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
276         }
277
278         public void RunLclVarScenario_Load()
279         {
280             var firstOp = Avx.LoadVector256((Single*)(_dataTable.inArray1Ptr));
281             var secondOp = Avx.LoadVector256((Single*)(_dataTable.inArray2Ptr));
282             var thirdOp = Avx.LoadVector256((Single*)(_dataTable.inArray3Ptr));
283             var result = Fma.MultiplySubtractAdd(firstOp, secondOp, thirdOp);
284
285             Unsafe.Write(_dataTable.outArrayPtr, result);
286             ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
287         }
288
289         public void RunLclVarScenario_LoadAligned()
290         {
291             var firstOp = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray1Ptr));
292             var secondOp = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray2Ptr));
293             var thirdOp = Avx.LoadAlignedVector256((Single*)(_dataTable.inArray3Ptr));
294             var result = Fma.MultiplySubtractAdd(firstOp, secondOp, thirdOp);
295
296             Unsafe.Write(_dataTable.outArrayPtr, result);
297             ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
298         }
299
300         public void RunClassLclFldScenario()
301         {
302             var test = new AlternatingTernaryOpTest__MultiplySubtractAddSingle();
303             var result = Fma.MultiplySubtractAdd(test._fld1, test._fld2, test._fld3);
304
305             Unsafe.Write(_dataTable.outArrayPtr, result);
306             ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
307         }
308
309         public void RunClassFldScenario()
310         {
311             var result = Fma.MultiplySubtractAdd(_fld1, _fld2, _fld3);
312
313             Unsafe.Write(_dataTable.outArrayPtr, result);
314             ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
315         }
316
317         public void RunStructLclFldScenario()
318         {
319             var test = TestStruct.Create();
320             var result = Fma.MultiplySubtractAdd(test._fld1, test._fld2, test._fld3);
321
322             Unsafe.Write(_dataTable.outArrayPtr, result);
323             ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
324         }
325
326         public void RunStructFldScenario()
327         {
328             var test = TestStruct.Create();
329             test.RunStructFldScenario(this);
330         }
331
332         public void RunUnsupportedScenario()
333         {
334             Succeeded = false;
335
336             try
337             {
338                 RunBasicScenario_UnsafeRead();
339             }
340             catch (PlatformNotSupportedException)
341             {
342                 Succeeded = true;
343             }
344         }
345
346         private void ValidateResult(Vector256<Single> firstOp, Vector256<Single> secondOp, Vector256<Single> thirdOp, void* result, [CallerMemberName] string method = "")
347         {
348             Single[] inArray1 = new Single[Op1ElementCount];
349             Single[] inArray2 = new Single[Op2ElementCount];
350             Single[] inArray3 = new Single[Op3ElementCount];
351             Single[] outArray = new Single[RetElementCount];
352
353             Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), firstOp);
354             Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), secondOp);
355             Unsafe.WriteUnaligned(ref Unsafe.As<Single, byte>(ref inArray3[0]), thirdOp);
356             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
357
358             ValidateResult(inArray1, inArray2, inArray3, outArray, method);
359         }
360
361         private void ValidateResult(void* firstOp, void* secondOp, void* thirdOp, void* result, [CallerMemberName] string method = "")
362         {
363             Single[] inArray1 = new Single[Op1ElementCount];
364             Single[] inArray2 = new Single[Op2ElementCount];
365             Single[] inArray3 = new Single[Op3ElementCount];
366             Single[] outArray = new Single[RetElementCount];
367
368             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(firstOp), (uint)Unsafe.SizeOf<Vector256<Single>>());
369             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(secondOp), (uint)Unsafe.SizeOf<Vector256<Single>>());
370             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(thirdOp), (uint)Unsafe.SizeOf<Vector256<Single>>());
371             Unsafe.CopyBlockUnaligned(ref Unsafe.As<Single, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector256<Single>>());
372
373             ValidateResult(inArray1, inArray2, inArray3, outArray, method);
374         }
375
376         private void ValidateResult(Single[] firstOp, Single[] secondOp, Single[] thirdOp, Single[] result, [CallerMemberName] string method = "")
377         {
378             for (var i = 0; i < RetElementCount; i += 2)
379             {
380                 if (BitConverter.SingleToInt32Bits(MathF.Round((firstOp[i] * secondOp[i]) + thirdOp[i], 3)) != BitConverter.SingleToInt32Bits(MathF.Round(result[i], 3)))
381                 {
382                     Succeeded = false;
383                     break;
384                 }
385
386                 if (BitConverter.SingleToInt32Bits(MathF.Round((firstOp[i + 1] * secondOp[i + 1]) - thirdOp[i + 1], 3)) != BitConverter.SingleToInt32Bits(MathF.Round(result[i + 1], 3)))
387                 {
388                     Succeeded = false;
389                     break;
390                 }
391             }
392
393             if (!Succeeded)
394             {
395                 Console.WriteLine($"{nameof(Fma)}.{nameof(Fma.MultiplySubtractAdd)}<Single>(Vector256<Single>, Vector256<Single>, Vector256<Single>): {method} failed:");
396                 Console.WriteLine($"   firstOp: ({string.Join(", ", firstOp)})");
397                 Console.WriteLine($"  secondOp: ({string.Join(", ", secondOp)})");
398                 Console.WriteLine($"   thirdOp: ({string.Join(", ", thirdOp)})");
399                 Console.WriteLine($"    result: ({string.Join(", ", result)})");
400                 Console.WriteLine();
401             }
402         }
403     }
404 }