|
@@ -24,6 +24,7 @@ namespace SIMDFxpConvert
|
|
|
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)
|
|
|
{
|
|
@@ -74,6 +75,234 @@ namespace SIMDFxpConvert
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ 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<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
|
|
|
+ var minv = Vector512<float>.One * min;
|
|
|
+ var maxv = Vector512<float>.One * max;
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 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<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
|
|
|
+ var minv = Vector512<double>.One * min;
|
|
|
+ var maxv = Vector512<double>.One * max;
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 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<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
|
|
|
+ var minv = Unsafe.As<float,Vector512<float>>(ref min);
|
|
|
+ var maxv = Unsafe.As<float, Vector512<float>>(ref max);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 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<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
|
|
|
+ var minv = Unsafe.As<double, Vector512<double>>(ref min);
|
|
|
+ var maxv = Unsafe.As<double, Vector512<double>>(ref max);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 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<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
|
|
|
+ var minv = Vector512<float>.One * min;
|
|
|
+ var maxv = Vector512<float>.One * max;
|
|
|
+ ref var resultv = ref Unsafe.As<int, Vector512<int>>(ref result);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 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<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
|
|
|
+ var minv = Vector512<double>.One * min;
|
|
|
+ var maxv = Vector512<double>.One * max;
|
|
|
+ ref var resultv = ref Unsafe.As<long, Vector512<long>>(ref result);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 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<float, System.Runtime.Intrinsics.Vector512<float>>(ref value);
|
|
|
+ var minv = Unsafe.As<float, Vector512<float>>(ref min);
|
|
|
+ var maxv = Unsafe.As<float, Vector512<float>>(ref max);
|
|
|
+ ref var resultv = ref Unsafe.As<int, Vector512<int>>(ref result);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<float>() * 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<double, System.Runtime.Intrinsics.Vector512<double>>(ref value);
|
|
|
+ var minv = Unsafe.As<double, Vector512<double>>(ref min);
|
|
|
+ var maxv = Unsafe.As<double, Vector512<double>>(ref max);
|
|
|
+ ref var resultv = ref Unsafe.As<long, Vector512<long>>(ref result);
|
|
|
+ uint onecount = (uint)(512 / (Unsafe.SizeOf<double>() * 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)
|