public TolerantMath(double epsilon) { DebugGuard.MustBeGreaterThan(epsilon, 0, nameof(epsilon)); this.epsilon = epsilon; this.negEpsilon = -epsilon; }
public DefaultShuffle3(byte p2, byte p1, byte p0) { DebugGuard.MustBeBetweenOrEqualTo <byte>(p2, 0, 2, nameof(p2)); DebugGuard.MustBeBetweenOrEqualTo <byte>(p1, 0, 2, nameof(p1)); DebugGuard.MustBeBetweenOrEqualTo <byte>(p0, 0, 2, nameof(p0)); this.p2 = p2; this.p1 = p1; this.p0 = p0; this.Control = SimdUtils.Shuffle.MmShuffle(3, p2, p1, p0); }
/// <summary> /// Convert 'source.Length' <see cref="float"/> values normalized into [0..1] from 'source' into 'dest' buffer of <see cref="byte"/> values. /// The values gonna be scaled up into [0-255] and rounded. /// Based on: /// <see> /// <cref>http://lolengine.net/blog/2011/3/20/understanding-fast-float-integer-conversions</cref> /// </see> /// </summary> internal static void BulkConvertNormalizedFloatToByte(ReadOnlySpan <float> source, Span <byte> dest) { GuardAvx2(nameof(BulkConvertNormalizedFloatToByte)); DebugGuard.IsTrue((source.Length % Vector <float> .Count) == 0, nameof(source), "source.Length should be divisable by Vector<float>.Count!"); if (source.Length == 0) { return; } ref Vector <float> srcBase = ref Unsafe.As <float, Vector <float> >(ref source.DangerousGetPinnableReference());
internal static void BulkConvertNormalizedFloatToByteClampOverflows(ReadOnlySpan <float> source, Span <byte> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); #if SUPPORTS_EXTENDED_INTRINSICS ExtendedIntrinsics.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest); #else BasicIntrinsics256.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest); #endif FallbackIntrinsics128.BulkConvertNormalizedFloatToByteClampOverflowsReduce(ref source, ref dest); // Deal with the remainder: if (source.Length > 0) { ConvertNormalizedFloatToByteRemainder(source, dest); } }
internal static void BulkConvertByteToNormalizedFloat(ReadOnlySpan <byte> source, Span <float> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); #if NETCOREAPP2_1 ExtendedIntrinsics.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest); #else BasicIntrinsics256.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest); #endif FallbackIntrinsics128.BulkConvertByteToNormalizedFloatReduce(ref source, ref dest); // Deal with the remainder: if (source.Length > 0) { ConverByteToNormalizedFloatRemainder(source, dest); } }
internal static void ByteToNormalizedFloat(ReadOnlySpan <byte> source, Span <float> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); #if SUPPORTS_EXTENDED_INTRINSICS ExtendedIntrinsics.ByteToNormalizedFloatReduce(ref source, ref dest); #else BasicIntrinsics256.ByteToNormalizedFloatReduce(ref source, ref dest); #endif // Also deals with the remainder from previous conversions: FallbackIntrinsics128.ByteToNormalizedFloatReduce(ref source, ref dest); // Deal with the remainder: if (source.Length > 0) { ConvertByteToNormalizedFloatRemainder(source, dest); } }
internal static void BulkConvertNormalizedFloatToByteClampOverflowsReduce( ref ReadOnlySpan <float> source, ref Span <byte> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); int remainder = ImageMaths.Modulo4(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) { BulkConvertNormalizedFloatToByteClampOverflows( source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); source = source.Slice(adjustedCount); dest = dest.Slice(adjustedCount); } }
internal static void NormalizedFloatToByteSaturateReduce( ref ReadOnlySpan <float> source, ref Span <byte> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); int remainder = Numerics.Modulo4(source.Length); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) { NormalizedFloatToByteSaturate( source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); source = source.Slice(adjustedCount); dest = dest.Slice(adjustedCount); } }
/// <summary> /// SIMD optimized bulk implementation of <see cref="IPixel.PackFromVector4(Vector4)"/> /// that works only with `count` divisible by <see cref="Vector{UInt32}.Count"/>. /// </summary> /// <param name="sourceColors">The <see cref="Span{T}"/> to the source colors.</param> /// <param name="destVectors">The <see cref="Span{T}"/> to the dstination vectors.</param> /// <param name="count">The number of pixels to convert.</param> /// <remarks> /// Implementation adapted from: /// <see> /// <cref>http://stackoverflow.com/a/5362789</cref> /// </see> /// TODO: We can replace this implementation in the future using new Vector API-s: /// <see> /// <cref>https://github.com/dotnet/corefx/issues/15957</cref> /// </see> /// </remarks> internal static void ToVector4SimdAligned(Span <Rgba32> sourceColors, Span <Vector4> destVectors, int count) { if (!Vector.IsHardwareAccelerated) { throw new InvalidOperationException( "Rgba32.PixelOperations.ToVector4SimdAligned() should not be called when Vector.IsHardwareAccelerated == false!"); } DebugGuard.IsTrue( count % Vector <uint> .Count == 0, nameof(count), "Argument 'count' should divisible by Vector<uint>.Count!"); var bVec = new Vector <float>(256.0f / 255.0f); var magicFloat = new Vector <float>(32768.0f); var magicInt = new Vector <uint>(1191182336); // reinterpreded value of 32768.0f var mask = new Vector <uint>(255); int unpackedRawCount = count * 4; ref uint sourceBase = ref Unsafe.As <Rgba32, uint>(ref sourceColors.DangerousGetPinnableReference());
internal static void BulkConvertByteToNormalizedFloatReduce( ref ReadOnlySpan <byte> source, ref Span <float> dest) { DebugGuard.IsTrue(source.Length == dest.Length, nameof(source), "Input spans must be of same length!"); if (!IsAvailable) { return; } int remainder = ImageMaths.ModuloP2(source.Length, Vector <byte> .Count); int adjustedCount = source.Length - remainder; if (adjustedCount > 0) { BulkConvertByteToNormalizedFloat(source.Slice(0, adjustedCount), dest.Slice(0, adjustedCount)); source = source.Slice(adjustedCount); dest = dest.Slice(adjustedCount); } }
internal static void PackFromRgbPlanes( Configuration configuration, ReadOnlySpan <byte> redChannel, ReadOnlySpan <byte> greenChannel, ReadOnlySpan <byte> blueChannel, Span <Rgba32> destination) { DebugGuard.IsTrue(greenChannel.Length == redChannel.Length, nameof(greenChannel), "Channels must be of same size!"); DebugGuard.IsTrue(blueChannel.Length == redChannel.Length, nameof(blueChannel), "Channels must be of same size!"); DebugGuard.IsTrue(destination.Length > redChannel.Length, nameof(destination), "'destination' span should not be shorter than the source channels!"); #if SUPPORTS_RUNTIME_INTRINSICS if (Avx2.IsSupported) { HwIntrinsics.PackFromRgbPlanesAvx2Reduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } else #endif { PackFromRgbPlanesScalarBatchedReduce(ref redChannel, ref greenChannel, ref blueChannel, ref destination); } PackFromRgbPlanesRemainder(redChannel, greenChannel, blueChannel, destination); }
public static ref Rgb24 GetRgb24(this Span <byte> bytes, int offset) { DebugGuard.MustBeLessThan(offset + 2, bytes.Length, nameof(offset)); return(ref Unsafe.As <byte, Rgb24>(ref bytes[offset])); }