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 /******************************************************************************
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 ******************************************************************************/
13 using System.Runtime.CompilerServices;
14 using System.Runtime.InteropServices;
15 using System.Runtime.Intrinsics;
16 using System.Runtime.Intrinsics.X86;
18 namespace JIT.HardwareIntrinsics.X86
20 public static partial class Program
22 private static void MultiplySubtractScalarDouble()
24 var test = new SimpleTernaryOpTest__MultiplySubtractScalarDouble();
28 // Validates basic functionality works, using Unsafe.Read
29 test.RunBasicScenario_UnsafeRead();
33 // Validates basic functionality works, using Load
34 test.RunBasicScenario_Load();
36 // Validates basic functionality works, using LoadAligned
37 test.RunBasicScenario_LoadAligned();
40 // Validates calling via reflection works, using Unsafe.Read
41 test.RunReflectionScenario_UnsafeRead();
45 // Validates calling via reflection works, using Load
46 test.RunReflectionScenario_Load();
48 // Validates calling via reflection works, using LoadAligned
49 test.RunReflectionScenario_LoadAligned();
52 // Validates passing a static member works
53 test.RunClsVarScenario();
55 // Validates passing a local works, using Unsafe.Read
56 test.RunLclVarScenario_UnsafeRead();
60 // Validates passing a local works, using Load
61 test.RunLclVarScenario_Load();
63 // Validates passing a local works, using LoadAligned
64 test.RunLclVarScenario_LoadAligned();
67 // Validates passing the field of a local class works
68 test.RunClassLclFldScenario();
70 // Validates passing an instance member of a class works
71 test.RunClassFldScenario();
73 // Validates passing the field of a local struct works
74 test.RunStructLclFldScenario();
76 // Validates passing an instance member of a struct works
77 test.RunStructFldScenario();
81 // Validates we throw on unsupported hardware
82 test.RunUnsupportedScenario();
87 throw new Exception("One or more scenarios did not complete as expected.");
92 public sealed unsafe class SimpleTernaryOpTest__MultiplySubtractScalarDouble
94 private struct TestStruct
96 public Vector128<Double> _fld1;
97 public Vector128<Double> _fld2;
98 public Vector128<Double> _fld3;
100 public static TestStruct Create()
102 var testStruct = new TestStruct();
103 var random = new Random();
105 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
106 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
107 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
108 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref testStruct._fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
109 for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (double)(random.NextDouble()); }
110 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar3), ref Unsafe.As<Double, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
115 public void RunStructFldScenario(SimpleTernaryOpTest__MultiplySubtractScalarDouble testClass)
117 var result = Fma.MultiplySubtractScalar(_fld1, _fld2, _fld3);
119 Unsafe.Write(testClass._dataTable.outArrayPtr, result);
120 testClass.ValidateResult(_fld1, _fld2, _fld3, testClass._dataTable.outArrayPtr);
124 private static readonly int LargestVectorSize = 16;
126 private static readonly int Op1ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
127 private static readonly int Op2ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
128 private static readonly int Op3ElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
129 private static readonly int RetElementCount = Unsafe.SizeOf<Vector128<Double>>() / sizeof(Double);
131 private static Double[] _data1 = new Double[Op1ElementCount];
132 private static Double[] _data2 = new Double[Op2ElementCount];
133 private static Double[] _data3 = new Double[Op3ElementCount];
135 private static Vector128<Double> _clsVar1;
136 private static Vector128<Double> _clsVar2;
137 private static Vector128<Double> _clsVar3;
139 private Vector128<Double> _fld1;
140 private Vector128<Double> _fld2;
141 private Vector128<Double> _fld3;
143 private SimpleTernaryOpTest__DataTable<Double, Double, Double, Double> _dataTable;
145 static SimpleTernaryOpTest__MultiplySubtractScalarDouble()
147 var random = new Random();
149 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
150 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
151 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
152 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
153 for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (double)(random.NextDouble()); }
154 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _clsVar3), ref Unsafe.As<Double, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
157 public SimpleTernaryOpTest__MultiplySubtractScalarDouble()
161 var random = new Random();
163 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
164 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld1), ref Unsafe.As<Double, byte>(ref _data1[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
165 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
166 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld2), ref Unsafe.As<Double, byte>(ref _data2[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
167 for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (double)(random.NextDouble()); }
168 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Vector128<Double>, byte>(ref _fld3), ref Unsafe.As<Double, byte>(ref _data3[0]), (uint)Unsafe.SizeOf<Vector128<Double>>());
170 for (var i = 0; i < Op1ElementCount; i++) { _data1[i] = (double)(random.NextDouble()); }
171 for (var i = 0; i < Op2ElementCount; i++) { _data2[i] = (double)(random.NextDouble()); }
172 for (var i = 0; i < Op3ElementCount; i++) { _data3[i] = (double)(random.NextDouble()); }
173 _dataTable = new SimpleTernaryOpTest__DataTable<Double, Double, Double, Double>(_data1, _data2, _data3, new Double[RetElementCount], LargestVectorSize);
176 public bool IsSupported => Fma.IsSupported;
178 public bool Succeeded { get; set; }
180 public void RunBasicScenario_UnsafeRead()
182 var result = Fma.MultiplySubtractScalar(
183 Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
184 Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr),
185 Unsafe.Read<Vector128<Double>>(_dataTable.inArray3Ptr)
188 Unsafe.Write(_dataTable.outArrayPtr, result);
189 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
192 public void RunBasicScenario_Load()
194 var result = Fma.MultiplySubtractScalar(
195 Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
196 Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)),
197 Sse2.LoadVector128((Double*)(_dataTable.inArray3Ptr))
200 Unsafe.Write(_dataTable.outArrayPtr, result);
201 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
204 public void RunBasicScenario_LoadAligned()
206 var result = Fma.MultiplySubtractScalar(
207 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
208 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)),
209 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray3Ptr))
212 Unsafe.Write(_dataTable.outArrayPtr, result);
213 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
216 public void RunReflectionScenario_UnsafeRead()
218 var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>), typeof(Vector128<Double>) })
219 .Invoke(null, new object[] {
220 Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr),
221 Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr),
222 Unsafe.Read<Vector128<Double>>(_dataTable.inArray3Ptr)
225 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
226 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
229 public void RunReflectionScenario_Load()
231 var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>), typeof(Vector128<Double>) })
232 .Invoke(null, new object[] {
233 Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr)),
234 Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr)),
235 Sse2.LoadVector128((Double*)(_dataTable.inArray3Ptr))
238 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
239 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
242 public void RunReflectionScenario_LoadAligned()
244 var result = typeof(Fma).GetMethod(nameof(Fma.MultiplySubtractScalar), new Type[] { typeof(Vector128<Double>), typeof(Vector128<Double>), typeof(Vector128<Double>) })
245 .Invoke(null, new object[] {
246 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr)),
247 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr)),
248 Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray3Ptr))
251 Unsafe.Write(_dataTable.outArrayPtr, (Vector128<Double>)(result));
252 ValidateResult(_dataTable.inArray1Ptr, _dataTable.inArray2Ptr, _dataTable.inArray3Ptr, _dataTable.outArrayPtr);
255 public void RunClsVarScenario()
257 var result = Fma.MultiplySubtractScalar(
263 Unsafe.Write(_dataTable.outArrayPtr, result);
264 ValidateResult(_clsVar1, _clsVar2, _clsVar3, _dataTable.outArrayPtr);
267 public void RunLclVarScenario_UnsafeRead()
269 var firstOp = Unsafe.Read<Vector128<Double>>(_dataTable.inArray1Ptr);
270 var secondOp = Unsafe.Read<Vector128<Double>>(_dataTable.inArray2Ptr);
271 var thirdOp = Unsafe.Read<Vector128<Double>>(_dataTable.inArray3Ptr);
272 var result = Fma.MultiplySubtractScalar(firstOp, secondOp, thirdOp);
274 Unsafe.Write(_dataTable.outArrayPtr, result);
275 ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
278 public void RunLclVarScenario_Load()
280 var firstOp = Sse2.LoadVector128((Double*)(_dataTable.inArray1Ptr));
281 var secondOp = Sse2.LoadVector128((Double*)(_dataTable.inArray2Ptr));
282 var thirdOp = Sse2.LoadVector128((Double*)(_dataTable.inArray3Ptr));
283 var result = Fma.MultiplySubtractScalar(firstOp, secondOp, thirdOp);
285 Unsafe.Write(_dataTable.outArrayPtr, result);
286 ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
289 public void RunLclVarScenario_LoadAligned()
291 var firstOp = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray1Ptr));
292 var secondOp = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray2Ptr));
293 var thirdOp = Sse2.LoadAlignedVector128((Double*)(_dataTable.inArray3Ptr));
294 var result = Fma.MultiplySubtractScalar(firstOp, secondOp, thirdOp);
296 Unsafe.Write(_dataTable.outArrayPtr, result);
297 ValidateResult(firstOp, secondOp, thirdOp, _dataTable.outArrayPtr);
300 public void RunClassLclFldScenario()
302 var test = new SimpleTernaryOpTest__MultiplySubtractScalarDouble();
303 var result = Fma.MultiplySubtractScalar(test._fld1, test._fld2, test._fld3);
305 Unsafe.Write(_dataTable.outArrayPtr, result);
306 ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
309 public void RunClassFldScenario()
311 var result = Fma.MultiplySubtractScalar(_fld1, _fld2, _fld3);
313 Unsafe.Write(_dataTable.outArrayPtr, result);
314 ValidateResult(_fld1, _fld2, _fld3, _dataTable.outArrayPtr);
317 public void RunStructLclFldScenario()
319 var test = TestStruct.Create();
320 var result = Fma.MultiplySubtractScalar(test._fld1, test._fld2, test._fld3);
322 Unsafe.Write(_dataTable.outArrayPtr, result);
323 ValidateResult(test._fld1, test._fld2, test._fld3, _dataTable.outArrayPtr);
326 public void RunStructFldScenario()
328 var test = TestStruct.Create();
329 test.RunStructFldScenario(this);
332 public void RunUnsupportedScenario()
338 RunBasicScenario_UnsafeRead();
340 catch (PlatformNotSupportedException)
346 private void ValidateResult(Vector128<Double> firstOp, Vector128<Double> secondOp, Vector128<Double> thirdOp, void* result, [CallerMemberName] string method = "")
348 Double[] inArray1 = new Double[Op1ElementCount];
349 Double[] inArray2 = new Double[Op2ElementCount];
350 Double[] inArray3 = new Double[Op3ElementCount];
351 Double[] outArray = new Double[RetElementCount];
353 Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), firstOp);
354 Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), secondOp);
355 Unsafe.WriteUnaligned(ref Unsafe.As<Double, byte>(ref inArray3[0]), thirdOp);
356 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
358 ValidateResult(inArray1, inArray2, inArray3, outArray, method);
361 private void ValidateResult(void* firstOp, void* secondOp, void* thirdOp, void* result, [CallerMemberName] string method = "")
363 Double[] inArray1 = new Double[Op1ElementCount];
364 Double[] inArray2 = new Double[Op2ElementCount];
365 Double[] inArray3 = new Double[Op3ElementCount];
366 Double[] outArray = new Double[RetElementCount];
368 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray1[0]), ref Unsafe.AsRef<byte>(firstOp), (uint)Unsafe.SizeOf<Vector128<Double>>());
369 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray2[0]), ref Unsafe.AsRef<byte>(secondOp), (uint)Unsafe.SizeOf<Vector128<Double>>());
370 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref inArray3[0]), ref Unsafe.AsRef<byte>(thirdOp), (uint)Unsafe.SizeOf<Vector128<Double>>());
371 Unsafe.CopyBlockUnaligned(ref Unsafe.As<Double, byte>(ref outArray[0]), ref Unsafe.AsRef<byte>(result), (uint)Unsafe.SizeOf<Vector128<Double>>());
373 ValidateResult(inArray1, inArray2, inArray3, outArray, method);
376 private void ValidateResult(Double[] firstOp, Double[] secondOp, Double[] thirdOp, Double[] result, [CallerMemberName] string method = "")
378 if (BitConverter.DoubleToInt64Bits(Math.Round((firstOp[0] * secondOp[0]) - thirdOp[0], 9)) != BitConverter.DoubleToInt64Bits(Math.Round(result[0], 9)))
384 for (var i = 1; i < RetElementCount; i++)
386 if (BitConverter.DoubleToInt64Bits(firstOp[i]) != BitConverter.DoubleToInt64Bits(result[i]))
396 Console.WriteLine($"{nameof(Fma)}.{nameof(Fma.MultiplySubtractScalar)}<Double>(Vector128<Double>, Vector128<Double>, Vector128<Double>): {method} failed:");
397 Console.WriteLine($" firstOp: ({string.Join(", ", firstOp)})");
398 Console.WriteLine($" secondOp: ({string.Join(", ", secondOp)})");
399 Console.WriteLine($" thirdOp: ({string.Join(", ", thirdOp)})");
400 Console.WriteLine($" result: ({string.Join(", ", result)})");