using FFTW.NET; using FxpConvert.Common; using System; using System.Collections.Generic; using System.Linq; using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.Intrinsics; using System.Text; using System.Threading.Tasks; namespace SIMDFxpConvert { public sealed class SIMDCalc : ICalc { public IAdd Add { get; } = new SIMDAdd(); public ISubtract Subtract { get; } = new SIMDSubtract(); public IMultiply Multiply { get; } = new SIMDMultiply(); public IDivision Division { get; } = new SIMDDivision(); public IFFT FFT { get; } = new SIMDFFT(); public IArraySum Sum { get; } = new SIMDArraySum(); public IClamp Clamp { get; } = new SIMDClamp(); public unsafe void Fill(ref float result, float value, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref result); var desc = Vector512.One * value; uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc = desc; } if (c1 > 0) { float* resultptr = (float*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = value; } } } public unsafe void Fill(ref double result, double value, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref result); var desc = Vector512.One * value; uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc = desc; } if (c1 > 0) { double* resultptr = (double*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = value; } } } } public sealed class SIMDClamp : IClamp { public unsafe void Clamp(ref float value, float min, float max, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Vector512.One * min; var maxv = Vector512.One * max; uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc =Vector512.Min(Vector512.Max(tempdesc,minv),maxv); } if (c1 > 0) { float* resultptr = (float*)Unsafe.AsPointer(ref value); for (int i = 0; i < c1; i++) { resultptr[start + i] = Math.Clamp(resultptr[start + i], min, max); } } } public unsafe void Clamp(ref double value, double min, double max, uint count) { ref var source = ref Unsafe.As>(ref value); var minv = Vector512.One * min; var maxv = Vector512.One * max; uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc = Vector512.Min(Vector512.Max(tempdesc, minv), maxv); } if (c1 > 0) { double* resultptr = (double*)Unsafe.AsPointer(ref value); for (int i = 0; i < c1; i++) { resultptr[start + i] = Math.Clamp(resultptr[start + i], min, max); } } } public unsafe void Clamp(ref float value, ref float min, ref float max, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Unsafe.As>(ref min); var maxv = Unsafe.As>(ref max); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc = Vector512.Min(Vector512.Max(tempdesc, Unsafe.Add(ref minv, i)), Unsafe.Add(ref maxv, i)); } if (c1 > 0) { float* resultptr = (float*)Unsafe.AsPointer(ref value); for (int i = 0; i < c1; i++) { resultptr[start + i] = Math.Clamp(resultptr[start + i], ((float*)Unsafe.AsPointer(ref min))[start + i], ((float*)Unsafe.AsPointer(ref max))[start + i]); } } } public unsafe void Clamp(ref double value, ref double min, ref double max, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Unsafe.As>(ref min); var maxv = Unsafe.As>(ref max); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc = Vector512.Min(Vector512.Max(tempdesc, Unsafe.Add(ref minv, i)), Unsafe.Add(ref maxv, i)); } if (c1 > 0) { double* resultptr = (double*)Unsafe.AsPointer(ref value); for (int i = 0; i < c1; i++) { resultptr[start + i] = Math.Clamp(resultptr[start + i], ((double*)Unsafe.AsPointer(ref min))[start + i], ((double*)Unsafe.AsPointer(ref max))[start + i]); } } } public unsafe void In(ref float value, float min, float max, uint count, ref int result) { if (count == 0) return ; ref var source = ref Unsafe.As>(ref value); var minv = Vector512.One * min; var maxv = Vector512.One * max; ref var resultv = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); var r1 = Vector512.LessThan(tempdesc, minv).AsInt32(); var r2 = Vector512.GreaterThan(tempdesc, maxv).AsInt32(); ref var tempresv = ref Unsafe.Add(ref resultv, i); tempresv = r1 | r2; } if (c1 > 0) { float* valueptr = (float*)Unsafe.AsPointer(ref value); int* resultptr = (int*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = valueptr[start + i] < min || valueptr[start + i] > max ? -1 : 0; } } } public unsafe void In(ref double value, double min, double max, uint count, ref long result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Vector512.One * min; var maxv = Vector512.One * max; ref var resultv = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); var r1 = Vector512.LessThan(tempdesc, minv).AsInt64(); var r2 = Vector512.GreaterThan(tempdesc, maxv).AsInt64(); ref var tempresv = ref Unsafe.Add(ref resultv, i); tempresv = r1 | r2; } if (c1 > 0) { double* valueptr = (double*)Unsafe.AsPointer(ref value); long* resultptr = (long*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = valueptr[start + i] < min || valueptr[start + i] > max ? -1 : 0; } } } public unsafe void In(ref float value, ref float min, ref float max, uint count, ref int result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Unsafe.As>(ref min); var maxv = Unsafe.As>(ref max); ref var resultv = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); var r1 = Vector512.LessThan(tempdesc, Unsafe.Add(ref minv, i)).AsInt32(); var r2 = Vector512.GreaterThan(tempdesc, Unsafe.Add(ref maxv, i)).AsInt32(); ref var tempresv = ref Unsafe.Add(ref resultv, i); tempresv = r1 | r2; } if (c1 > 0) { float* valueptr = (float*)Unsafe.AsPointer(ref value); float* mintr = (float*)Unsafe.AsPointer(ref min); float* maxptr = (float*)Unsafe.AsPointer(ref max); int* resultptr = (int*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = valueptr[start + i] < mintr[start + i] || valueptr[start + i] > maxptr[start + i] ? -1 : 0; } } } public unsafe void In(ref double value, ref double min, ref double max, uint count, ref long result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref value); var minv = Unsafe.As>(ref min); var maxv = Unsafe.As>(ref max); ref var resultv = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); var r1 = Vector512.LessThan(tempdesc, Unsafe.Add(ref minv, i)).AsInt64(); var r2 = Vector512.GreaterThan(tempdesc, Unsafe.Add(ref maxv, i)).AsInt64(); ref var tempresv = ref Unsafe.Add(ref resultv, i); tempresv = r1 | r2; } if (c1 > 0) { double* valueptr = (double*)Unsafe.AsPointer(ref value); double* mintr = (double*)Unsafe.AsPointer(ref min); double* maxptr = (double*)Unsafe.AsPointer(ref max); long* resultptr = (long*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = valueptr[start + i] < mintr[start + i] || valueptr[start + i] > maxptr[start + i] ? -1 : 0; } } } } public sealed class SIMDArraySum : IArraySum { public unsafe float Rms(ref float value, uint count) { if (count == 0) return 0; if (count == 1) return value; float temp = 0; float* ptr = (float*)Unsafe.AsPointer(ref value); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var refvalue = ref Unsafe.As>(ref value); for (int i = 0; i < c; i++) { ref var tempref = ref Unsafe.Add(ref refvalue, i); var t = tempref * tempref; temp += Vector512.Sum(tempref); } if (c1 > 0) { for (int i = 0; i < c1; i++) { temp += (ptr[start + i] * ptr[start + i]); } } return MathF.Sqrt(temp / count); } public unsafe double Rms(ref double value, uint count) { if (count == 0) return 0; if (count == 1) return value; double temp = 0; double* ptr = (double*)Unsafe.AsPointer(ref value); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var refvalue = ref Unsafe.As>(ref value); for (int i = 0; i < c; i++) { ref var tempref = ref Unsafe.Add(ref refvalue, i); tempref *= tempref; temp += Vector512.Sum(tempref); } if (c1 > 0) { for (int i = 0; i < c1; i++) { temp += (ptr[start + i] * ptr[start + i]); } } return Math.Sqrt(temp / count); } public unsafe float Sum(ref float value, uint count) { if (count == 0) return 0; if (count == 1) return value; float temp = 0; float* ptr = (float*)Unsafe.AsPointer(ref value); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var refvalue = ref Unsafe.As>(ref value); for (int i = 0; i < c; i++) { temp += Vector512.Sum(Unsafe.Add(ref refvalue, i)); } if (c1 > 0) { for (int i = 0; i < c1; i++) { temp += (ptr[start + i] * ptr[start + i]); } } return temp; } public unsafe double Sum(ref double value, uint count) { if (count == 0) return 0; if (count == 1) return value; double temp = 0; double* ptr = (double*)Unsafe.AsPointer(ref value); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var refvalue = ref Unsafe.As>(ref value); for (int i = 0; i < c; i++) { temp += Vector512.Sum(Unsafe.Add(ref refvalue, i)); } if (c1 > 0) { for (int i = 0; i < c1; i++) { temp += (ptr[start + i] * ptr[start + i]); } } return temp; } } public sealed class SIMDFFT : IFFT { public SIMDFFT() { FFTW.NET.FftwInterop.Initialize(); } public void FFT(double[] real, double[] imaginary) { var result = FFTW.NET.DFT.FFT(real, imaginary); var tempreal = result.Select(x => x.Real).ToArray(); var tempimg = result.Select(x => x.Imaginary).ToArray(); Unsafe.CopyBlock(ref Unsafe.As(ref real[0]), ref Unsafe.As(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf())); Unsafe.CopyBlock(ref Unsafe.As(ref imaginary[0]), ref Unsafe.As(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf())); } public void FFT(float[] real, float[] imaginary) { var result = FFTW.NET.DFT.FFT(real.Select(x=> (double)x).ToArray(), imaginary.Select(x=> (double)x).ToArray()); var tempreal = result.Select(x => (float)x.Real).ToArray(); var tempimg = result.Select(x => (float)x.Imaginary).ToArray(); Unsafe.CopyBlock(ref Unsafe.As(ref real[0]), ref Unsafe.As(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf())); Unsafe.CopyBlock(ref Unsafe.As(ref imaginary[0]), ref Unsafe.As(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf())); } public void IFFT(double[] real, double[] imaginary) { var result = FFTW.NET.DFT.IFFT(real, imaginary); var tempreal = result.Select(x => x.Real).ToArray(); var tempimg = result.Select(x => x.Imaginary).ToArray(); Unsafe.CopyBlock(ref Unsafe.As(ref real[0]), ref Unsafe.As(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf())); Unsafe.CopyBlock(ref Unsafe.As(ref imaginary[0]), ref Unsafe.As(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf())); } public void IFFT(float[] real, float[] imaginary) { var result = FFTW.NET.DFT.IFFT(real.Select(x => (double)x).ToArray(), imaginary.Select(x => (double)x).ToArray()); var tempreal = result.Select(x => (float)x.Real).ToArray(); var tempimg = result.Select(x => (float)x.Imaginary).ToArray(); Unsafe.CopyBlock(ref Unsafe.As(ref real[0]), ref Unsafe.As(ref tempreal[0]), (uint)(real.Length * Unsafe.SizeOf())); Unsafe.CopyBlock(ref Unsafe.As(ref imaginary[0]), ref Unsafe.As(ref tempimg[0]), (uint)(real.Length * Unsafe.SizeOf())); } } public unsafe sealed class SIMDAdd : IAdd { public void Add(ref float left, float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) + tempright; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] + right; } } } public void Add(ref float left, ref float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) + Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] + rightptr[start + i]; } } } public void Add(ref float left, float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc += tempright; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] += right; } } } public void Add(ref float left, ref float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc += Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] += rightptr[start + i]; } } } public void Add(ref double left, double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) + tempright; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] + right; } } } public void Add(ref double left, ref double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) + Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] + rightptr[start + i]; } } } public void Add(ref double left, double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc += tempright; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] += right; } } } public void Add(ref double left, ref double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc += Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] += rightptr[start + i]; } } } } public unsafe sealed class SIMDSubtract : ISubtract { public void Subtract(ref float left, float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) - tempright; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] - right; } } } public void Subtract(ref float left, ref float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) - Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] - rightptr[start + i]; } } } public void Subtract(ref float left, float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc -= tempright; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] -= right; } } } public void Subtract(ref float left, ref float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc -= Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] -= rightptr[start + i]; } } } public void Subtract(ref double left, double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) - tempright; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] - right; } } } public void Subtract(ref double left, ref double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) - Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] - rightptr[start + i]; } } } public void Subtract(ref double left, double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; var rightarray = Enumerable.Repeat(right, (int)onecount).ToArray(); ref var tempright = ref Unsafe.As>(ref rightarray[0]); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc -= tempright; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] -= right; } } } public void Subtract(ref double left, ref double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc -= Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] -= rightptr[start + i]; } } } } public unsafe sealed class SIMDMultiply : IMultiply { public void Multiply(ref float left, float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) * right; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] * right; } } } public void Multiply(ref float left, ref float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) * Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] * rightptr[start + i]; } } } public void Multiply(ref float left, float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc *= right; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] *= right; } } } public void Multiply(ref float left, ref float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc *= Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] *= rightptr[start + i]; } } } public void Multiply(ref double left, double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) * right; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] * right; } } } public void Multiply(ref double left, ref double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) * Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] * rightptr[start + i]; } } } public void Multiply(ref double left, double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc *= right; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] *= right; } } } public void Multiply(ref double left, ref double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc *= Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] *= rightptr[start + i]; } } } } public unsafe sealed class SIMDDivision : IDivision { public void Division(ref float left, float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) / right; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] / right; } } } public void Division(ref float left, ref float right, uint count, ref float result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) / Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* resultptr = (float*)Unsafe.AsPointer(ref result); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] / rightptr[start + i]; } } } public void Division(ref float left, float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc /= right; } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] /= right; } } } public void Division(ref float left, ref float right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc /= Unsafe.Add(ref tempright, i); } if (c1 > 0) { float* leftptr = (float*)Unsafe.AsPointer(ref left); float* rightptr = (float*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] /= rightptr[start + i]; } } } public void Division(ref double left, double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) / right; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] / right; } } } public void Division(ref double left, ref double right, uint count, ref double result) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); ref var desc = ref Unsafe.As>(ref result); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref desc, i); tempdesc = Unsafe.Add(ref source, i) / Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* resultptr = (double*)Unsafe.AsPointer(ref result); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { resultptr[start + i] = leftptr[start + i] / rightptr[start + i]; } } } public void Division(ref double left, double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc /= right; } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); for (int i = 0; i < c1; i++) { leftptr[start + i] /= right; } } } public void Division(ref double left, ref double right, uint count) { if (count == 0) return; ref var source = ref Unsafe.As>(ref left); uint onecount = (uint)(512 / (Unsafe.SizeOf() * 8)); uint c = count / onecount; uint c1 = count % onecount; uint start = c * onecount; ref var tempright = ref Unsafe.As>(ref right); for (int i = 0; i < c; i++) { ref var tempdesc = ref Unsafe.Add(ref source, i); tempdesc /= Unsafe.Add(ref tempright, i); } if (c1 > 0) { double* leftptr = (double*)Unsafe.AsPointer(ref left); double* rightptr = (double*)Unsafe.AsPointer(ref right); for (int i = 0; i < c1; i++) { leftptr[start + i] /= rightptr[start + i]; } } } } }