|
|
@ -41,13 +41,11 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Determine the Least Common Multiple (LCM) of two numbers.
|
|
|
/// Determine the Least Common Multiple (LCM) of two numbers.
|
|
|
|
|
|
/// See https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor.
|
|
|
/// </summary>
|
|
|
/// </summary>
|
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
[MethodImpl(MethodImplOptions.AggressiveInlining)] |
|
|
public static int LeastCommonMultiple(int a, int b) |
|
|
public static int LeastCommonMultiple(int a, int b) |
|
|
{ |
|
|
=> a / GreatestCommonDivisor(a, b) * b; |
|
|
// https://en.wikipedia.org/wiki/Least_common_multiple#Reduction_by_the_greatest_common_divisor
|
|
|
|
|
|
return (a / GreatestCommonDivisor(a, b)) * b; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
/// <summary>
|
|
|
/// Calculates <paramref name="x"/> % 2
|
|
|
/// Calculates <paramref name="x"/> % 2
|
|
|
@ -290,10 +288,14 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
if (remainder.Length > 0) |
|
|
if (remainder.Length > 0) |
|
|
{ |
|
|
{ |
|
|
for (int i = 0; i < remainder.Length; i++) |
|
|
ref byte remainderStart = ref MemoryMarshal.GetReference(remainder); |
|
|
|
|
|
ref byte remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); |
|
|
|
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) |
|
|
{ |
|
|
{ |
|
|
ref byte v = ref remainder[i]; |
|
|
remainderStart = Clamp(remainderStart, min, max); |
|
|
v = Clamp(v, min, max); |
|
|
|
|
|
|
|
|
remainderStart = ref Unsafe.Add(ref remainderStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -311,10 +313,14 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
if (remainder.Length > 0) |
|
|
if (remainder.Length > 0) |
|
|
{ |
|
|
{ |
|
|
for (int i = 0; i < remainder.Length; i++) |
|
|
ref uint remainderStart = ref MemoryMarshal.GetReference(remainder); |
|
|
|
|
|
ref uint remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); |
|
|
|
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) |
|
|
{ |
|
|
{ |
|
|
ref uint v = ref remainder[i]; |
|
|
remainderStart = Clamp(remainderStart, min, max); |
|
|
v = Clamp(v, min, max); |
|
|
|
|
|
|
|
|
remainderStart = ref Unsafe.Add(ref remainderStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -332,10 +338,14 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
if (remainder.Length > 0) |
|
|
if (remainder.Length > 0) |
|
|
{ |
|
|
{ |
|
|
for (int i = 0; i < remainder.Length; i++) |
|
|
ref int remainderStart = ref MemoryMarshal.GetReference(remainder); |
|
|
|
|
|
ref int remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); |
|
|
|
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) |
|
|
{ |
|
|
{ |
|
|
ref int v = ref remainder[i]; |
|
|
remainderStart = Clamp(remainderStart, min, max); |
|
|
v = Clamp(v, min, max); |
|
|
|
|
|
|
|
|
remainderStart = ref Unsafe.Add(ref remainderStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -353,10 +363,14 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
if (remainder.Length > 0) |
|
|
if (remainder.Length > 0) |
|
|
{ |
|
|
{ |
|
|
for (int i = 0; i < remainder.Length; i++) |
|
|
ref float remainderStart = ref MemoryMarshal.GetReference(remainder); |
|
|
|
|
|
ref float remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); |
|
|
|
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) |
|
|
{ |
|
|
{ |
|
|
ref float v = ref remainder[i]; |
|
|
remainderStart = Clamp(remainderStart, min, max); |
|
|
v = Clamp(v, min, max); |
|
|
|
|
|
|
|
|
remainderStart = ref Unsafe.Add(ref remainderStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -374,10 +388,14 @@ namespace SixLabors.ImageSharp |
|
|
|
|
|
|
|
|
if (remainder.Length > 0) |
|
|
if (remainder.Length > 0) |
|
|
{ |
|
|
{ |
|
|
for (int i = 0; i < remainder.Length; i++) |
|
|
ref double remainderStart = ref MemoryMarshal.GetReference(remainder); |
|
|
|
|
|
ref double remainderEnd = ref Unsafe.Add(ref remainderStart, remainder.Length); |
|
|
|
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref remainderStart, ref remainderEnd)) |
|
|
{ |
|
|
{ |
|
|
ref double v = ref remainder[i]; |
|
|
remainderStart = Clamp(remainderStart, min, max); |
|
|
v = Clamp(v, min, max); |
|
|
|
|
|
|
|
|
remainderStart = ref Unsafe.Add(ref remainderStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -472,10 +490,8 @@ namespace SixLabors.ImageSharp |
|
|
#if SUPPORTS_RUNTIME_INTRINSICS
|
|
|
#if SUPPORTS_RUNTIME_INTRINSICS
|
|
|
if (Avx2.IsSupported && vectors.Length >= 2) |
|
|
if (Avx2.IsSupported && vectors.Length >= 2) |
|
|
{ |
|
|
{ |
|
|
ref Vector256<float> vectorsBase = |
|
|
|
|
|
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|
|
|
|
|
|
|
|
|
|
|
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|
|
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|
|
|
|
|
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|
|
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|
|
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|
|
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|
|
@ -495,12 +511,14 @@ namespace SixLabors.ImageSharp |
|
|
else |
|
|
else |
|
|
#endif
|
|
|
#endif
|
|
|
{ |
|
|
{ |
|
|
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|
|
ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors); |
|
|
|
|
|
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); |
|
|
|
|
|
|
|
|
for (int i = 0; i < vectors.Length; i++) |
|
|
while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd)) |
|
|
{ |
|
|
{ |
|
|
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|
|
Premultiply(ref vectorsStart); |
|
|
Premultiply(ref v); |
|
|
|
|
|
|
|
|
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -515,10 +533,8 @@ namespace SixLabors.ImageSharp |
|
|
#if SUPPORTS_RUNTIME_INTRINSICS
|
|
|
#if SUPPORTS_RUNTIME_INTRINSICS
|
|
|
if (Avx2.IsSupported && vectors.Length >= 2) |
|
|
if (Avx2.IsSupported && vectors.Length >= 2) |
|
|
{ |
|
|
{ |
|
|
ref Vector256<float> vectorsBase = |
|
|
|
|
|
ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|
|
|
|
|
|
|
|
|
|
|
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|
|
// Divide by 2 as 4 elements per Vector4 and 8 per Vector256<float>
|
|
|
|
|
|
ref Vector256<float> vectorsBase = ref Unsafe.As<Vector4, Vector256<float>>(ref MemoryMarshal.GetReference(vectors)); |
|
|
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|
|
ref Vector256<float> vectorsLast = ref Unsafe.Add(ref vectorsBase, (IntPtr)((uint)vectors.Length / 2u)); |
|
|
|
|
|
|
|
|
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|
|
while (Unsafe.IsAddressLessThan(ref vectorsBase, ref vectorsLast)) |
|
|
@ -538,12 +554,14 @@ namespace SixLabors.ImageSharp |
|
|
else |
|
|
else |
|
|
#endif
|
|
|
#endif
|
|
|
{ |
|
|
{ |
|
|
ref Vector4 baseRef = ref MemoryMarshal.GetReference(vectors); |
|
|
ref Vector4 vectorsStart = ref MemoryMarshal.GetReference(vectors); |
|
|
|
|
|
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsStart, vectors.Length); |
|
|
|
|
|
|
|
|
for (int i = 0; i < vectors.Length; i++) |
|
|
while (Unsafe.IsAddressLessThan(ref vectorsStart, ref vectorsEnd)) |
|
|
{ |
|
|
{ |
|
|
ref Vector4 v = ref Unsafe.Add(ref baseRef, i); |
|
|
UnPremultiply(ref vectorsStart); |
|
|
UnPremultiply(ref v); |
|
|
|
|
|
|
|
|
vectorsStart = ref Unsafe.Add(ref vectorsStart, 1); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -633,10 +651,10 @@ namespace SixLabors.ImageSharp |
|
|
vectors128Ref = y4; |
|
|
vectors128Ref = y4; |
|
|
vectors128Ref = ref Unsafe.Add(ref vectors128Ref, 1); |
|
|
vectors128Ref = ref Unsafe.Add(ref vectors128Ref, 1); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
else |
|
|
#endif
|
|
|
#endif
|
|
|
|
|
|
{ |
|
|
ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors); |
|
|
ref Vector4 vectorsRef = ref MemoryMarshal.GetReference(vectors); |
|
|
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length); |
|
|
ref Vector4 vectorsEnd = ref Unsafe.Add(ref vectorsRef, vectors.Length); |
|
|
|
|
|
|
|
|
@ -684,3 +702,4 @@ namespace SixLabors.ImageSharp |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|