diff --git a/src/ImageSharp46/Formats/Jpg/Components/Buffer64.cs b/src/ImageSharp46/Formats/Jpg/Components/Buffer8x8.cs similarity index 75% rename from src/ImageSharp46/Formats/Jpg/Components/Buffer64.cs rename to src/ImageSharp46/Formats/Jpg/Components/Buffer8x8.cs index f3b47e3a4..546c712ac 100644 --- a/src/ImageSharp46/Formats/Jpg/Components/Buffer64.cs +++ b/src/ImageSharp46/Formats/Jpg/Components/Buffer8x8.cs @@ -4,27 +4,32 @@ using System.Runtime.CompilerServices; namespace ImageSharp.Formats { - public struct Buffer64 + // ReSharper disable once InconsistentNaming + public struct Buffer8x8 { - public Vector4 V00; - public Vector4 V01; - public Vector4 V02; - public Vector4 V03; + public Vector4 V0L; + public Vector4 V0R; - public Vector4 V10; - public Vector4 V11; - public Vector4 V12; - public Vector4 V13; + public Vector4 V1L; + public Vector4 V1R; - public Vector4 V20; - public Vector4 V21; - public Vector4 V22; - public Vector4 V23; + public Vector4 V2L; + public Vector4 V2R; - public Vector4 V30; - public Vector4 V31; - public Vector4 V32; - public Vector4 V33; + public Vector4 V3L; + public Vector4 V3R; + + public Vector4 V4L; + public Vector4 V4R; + + public Vector4 V5L; + public Vector4 V5R; + + public Vector4 V6L; + public Vector4 V6R; + + public Vector4 V7L; + public Vector4 V7R; public const int VectorCount = 16; @@ -32,7 +37,7 @@ namespace ImageSharp.Formats public unsafe void LoadFrom(Span source) { - fixed (Vector4* ptr = &V00) + fixed (Vector4* ptr = &V0L) { float* fp = (float*)ptr; for (int i = 0; i < ScalarCount; i++) @@ -44,7 +49,7 @@ namespace ImageSharp.Formats public unsafe void CopyTo(Span dest) { - fixed (Vector4* ptr = &V00) + fixed (Vector4* ptr = &V0L) { float* fp = (float*)ptr; for (int i = 0; i < ScalarCount; i++) @@ -56,7 +61,7 @@ namespace ImageSharp.Formats internal unsafe void LoadFrom(Span source) { - fixed (Vector4* ptr = &V00) + fixed (Vector4* ptr = &V0L) { float* fp = (float*)ptr; for (int i = 0; i < ScalarCount; i++) @@ -68,7 +73,7 @@ namespace ImageSharp.Formats internal unsafe void CopyTo(Span dest) { - fixed (Vector4* ptr = &V00) + fixed (Vector4* ptr = &V0L) { float* fp = (float*)ptr; for (int i = 0; i < ScalarCount; i++) @@ -80,7 +85,7 @@ namespace ImageSharp.Formats public unsafe void TransposeInplace() { - fixed (Vector4* ptr = &V00) + fixed (Vector4* ptr = &V0L) { float* data = (float*) ptr; @@ -98,13 +103,13 @@ namespace ImageSharp.Formats } - public unsafe void TranposeInto(ref Buffer64 destination) + public unsafe void TranposeInto(ref Buffer8x8 destination) { - fixed (Vector4* sPtr = &V00) + fixed (Vector4* sPtr = &V0L) { float* src = (float*)sPtr; - fixed (Vector4* dPtr = &destination.V00) + fixed (Vector4* dPtr = &destination.V0L) { float* dest = (float*) dPtr; @@ -120,21 +125,26 @@ namespace ImageSharp.Formats } } - //public struct Matrix - //{ - // public Matrix4x4 A, B, C, D; + public void TransposeIntoSafe(ref Buffer8x8 d) + { + + } - // public void LoadFrom(ref Buffer64 b) - // { - // fixed (Vector4*) - // } - //} - public void TransposeIntoSafe(ref Buffer64 destination) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void PinnedTransposeInto(Buffer8x8* sourcePtr, Buffer8x8* destPtr) { - Matrix4x4 a; - + float* src = (float*)sourcePtr; + float* dest = (float*) destPtr; + for (int i = 0; i < 8; i++) + { + int i8 = i * 8; + for (int j = 0; j < 8; j++) + { + dest[j * 8 + i] = src[i8 + j]; + } + } } private static readonly Vector4 _c = new Vector4(0.1250f); @@ -142,14 +152,14 @@ namespace ImageSharp.Formats [MethodImpl(MethodImplOptions.AggressiveInlining)] public void MultiplyAllInplace(Vector4 s) { - V00 *= s; V01 *= s; V02 *= s; V03 *= s; - V10 *= s; V11 *= s; V12 *= s; V13 *= s; - V20 *= s; V21 *= s; V22 *= s; V23 *= s; - V30 *= s; V31 *= s; V32 *= s; V33 *= s; + V0L *= s; V0R *= s; V1L *= s; V1R *= s; + V2L *= s; V2R *= s; V3L *= s; V3R *= s; + V4L *= s; V4R *= s; V5L *= s; V5R *= s; + V6L *= s; V6R *= s; V7L *= s; V7R *= s; } // ReSharper disable once InconsistentNaming - public void TransformIDCTInto(ref Buffer64 dest, ref Buffer64 temp) + public void TransformIDCTInto(ref Buffer8x8 dest, ref Buffer8x8 temp) { TranposeInto(ref temp); temp.iDCT2D8x4_LeftPart(ref dest); @@ -176,7 +186,7 @@ namespace ImageSharp.Formats private static readonly Vector4 _1_847759 = new Vector4(-1.847759f); private static readonly Vector4 _0_765367 = new Vector4(0.765367f); - internal void iDCT2D8x4_LeftPart(ref Buffer64 d) + internal void iDCT2D8x4_LeftPart(ref Buffer8x8 d) { /* float a0,a1,a2,a3,b0,b1,b2,b3; float z0,z1,z2,z3,z4; float r[8]; int i; @@ -193,13 +203,13 @@ namespace ImageSharp.Formats 7: 0.275899 */ - Vector4 my1 = V02; - Vector4 my7 = V32; + Vector4 my1 = V1L; + Vector4 my7 = V7L; Vector4 mz0 = my1 + my7; - Vector4 my3 = V12; + Vector4 my3 = V3L; Vector4 mz2 = my3 + my7; - Vector4 my5 = V22; + Vector4 my5 = V5L; Vector4 mz1 = my3 + my5; Vector4 mz3 = my1 + my5; @@ -239,11 +249,11 @@ namespace ImageSharp.Formats b0 = y[1] * ( r[1] + r[3] - r[5] - r[7]) + z0 + z3; */ - Vector4 my2 = V10; - Vector4 my6 = V30; + Vector4 my2 = V2L; + Vector4 my6 = V6L; mz4 = (my2 + my6) * _0_541196; - Vector4 my0 = V00; - Vector4 my4 = V20; + Vector4 my0 = V0L; + Vector4 my4 = V4L; mz0 = my0 + my4; mz1 = my0 - my4; @@ -265,14 +275,14 @@ namespace ImageSharp.Formats a1 = z1 + z2; a2 = z1 - z2; */ - d.V00 = my0 + mb0; - d.V32 = my0 - mb0; - d.V02 = my1 + mb1; - d.V30 = my1 - mb1; - d.V10 = my2 + mb2; - d.V22 = my2 - mb2; - d.V12 = my3 + mb3; - d.V20 = my3 - mb3; + d.V0L = my0 + mb0; + d.V7L = my0 - mb0; + d.V1L = my1 + mb1; + d.V6L = my1 - mb1; + d.V2L = my2 + mb2; + d.V5L = my2 - mb2; + d.V3L = my3 + mb3; + d.V4L = my3 - mb3; /* x[0] = a0 + b0; x[7] = a0 - b0; x[1] = a1 + b1; x[6] = a1 - b1; @@ -283,7 +293,7 @@ namespace ImageSharp.Formats } - internal void iDCT2D8x4_RightPart(ref Buffer64 d) + internal void iDCT2D8x4_RightPart(ref Buffer8x8 d) { /* float a0,a1,a2,a3,b0,b1,b2,b3; float z0,z1,z2,z3,z4; float r[8]; int i; @@ -300,13 +310,13 @@ namespace ImageSharp.Formats 7: 0.275899 */ - Vector4 my1 = V03; - Vector4 my7 = V33; + Vector4 my1 = V1R; + Vector4 my7 = V7R; Vector4 mz0 = my1 + my7; - Vector4 my3 = V13; + Vector4 my3 = V3R; Vector4 mz2 = my3 + my7; - Vector4 my5 = V23; + Vector4 my5 = V5R; Vector4 mz1 = my3 + my5; Vector4 mz3 = my1 + my5; @@ -346,11 +356,11 @@ namespace ImageSharp.Formats b0 = y[1] * ( r[1] + r[3] - r[5] - r[7]) + z0 + z3; */ - Vector4 my2 = V11; - Vector4 my6 = V31; + Vector4 my2 = V2R; + Vector4 my6 = V6R; mz4 = (my2 + my6) * _0_541196; - Vector4 my0 = V01; - Vector4 my4 = V21; + Vector4 my0 = V0R; + Vector4 my4 = V4R; mz0 = my0 + my4; mz1 = my0 - my4; @@ -372,14 +382,14 @@ namespace ImageSharp.Formats a1 = z1 + z2; a2 = z1 - z2; */ - d.V01 = my0 + mb0; - d.V33 = my0 - mb0; - d.V03 = my1 + mb1; - d.V31 = my1 - mb1; - d.V11 = my2 + mb2; - d.V23 = my2 - mb2; - d.V13 = my3 + mb3; - d.V21 = my3 - mb3; + d.V0R = my0 + mb0; + d.V7R = my0 - mb0; + d.V1R = my1 + mb1; + d.V6R = my1 - mb1; + d.V2R = my2 + mb2; + d.V5R = my2 - mb2; + d.V3R = my3 + mb3; + d.V4R = my3 - mb3; /* x[0] = a0 + b0; x[7] = a0 - b0; x[1] = a1 + b1; x[6] = a1 - b1; @@ -391,11 +401,11 @@ namespace ImageSharp.Formats public static void SuchIDCT(ref Block block) { - Buffer64 source = new Buffer64(); + Buffer8x8 source = new Buffer8x8(); source.LoadFrom(block.Data); - Buffer64 dest = new Buffer64(); - Buffer64 temp = new Buffer64(); + Buffer8x8 dest = new Buffer8x8(); + Buffer8x8 temp = new Buffer8x8(); source.TransformIDCTInto(ref dest, ref temp); dest.CopyTo(block.Data); diff --git a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs index 08368a31a..8578a4033 100644 --- a/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs +++ b/src/ImageSharp46/Formats/Jpg/JpegDecoderCore.cs @@ -1814,7 +1814,7 @@ namespace ImageSharp.Formats //IDCT.Transform(ref b); //FloatIDCT.Transform(ref b); //ReferenceDCT.IDCT(ref b); - Buffer64.SuchIDCT(ref b); + Buffer8x8.SuchIDCT(ref b); byte[] dst; int offset; diff --git a/src/ImageSharp46/ImageSharp46.csproj b/src/ImageSharp46/ImageSharp46.csproj index 64b931c0d..d783ac7e5 100644 --- a/src/ImageSharp46/ImageSharp46.csproj +++ b/src/ImageSharp46/ImageSharp46.csproj @@ -227,7 +227,7 @@ - + diff --git a/tests/ImageSharp.Tests46/Formats/Jpg/Buffer64Tests.cs b/tests/ImageSharp.Tests46/Formats/Jpg/Buffer64Tests.cs deleted file mode 100644 index be57d22d4..000000000 --- a/tests/ImageSharp.Tests46/Formats/Jpg/Buffer64Tests.cs +++ /dev/null @@ -1,180 +0,0 @@ -using System; -using System.Diagnostics; -using System.Numerics; -using System.Runtime.CompilerServices; -using ImageSharp.Formats; -using Xunit; -using Xunit.Abstractions; - -namespace ImageSharp.Tests.Formats.Jpg -{ - public class Buffer64Tests : UtilityTestClassBase - { - public Buffer64Tests(ITestOutputHelper output) : base(output) - { - } - - [Theory] - [InlineData(1)] - [InlineData(1000000)] - public void Load_Store_FloatArray(int times) - { - - - float[] data = new float[Buffer64.ScalarCount]; - float[] mirror = new float[Buffer64.ScalarCount]; - - for (int i = 0; i < Buffer64.ScalarCount; i++) - { - data[i] = i; - } - Measure(times, () => - { - Buffer64 v = new Buffer64(); - v.LoadFrom(data); - v.CopyTo(mirror); - }); - - Assert.Equal(data, mirror); - PrintLinearData((Span)mirror); - } - - [Theory] - [InlineData(1)] - [InlineData(1000000)] - public void Load_Store_IntArray(int times) - { - - - int[] data = new int[Buffer64.ScalarCount]; - int[] mirror = new int[Buffer64.ScalarCount]; - - for (int i = 0; i < Buffer64.ScalarCount; i++) - { - data[i] = i; - } - Measure(times, () => - { - Buffer64 v = new Buffer64(); - v.LoadFrom(data); - v.CopyTo(mirror); - }); - - Assert.Equal(data, mirror); - PrintLinearData((Span)mirror); - } - - [Fact] - public void TransposeInplace() - { - float[] expected = Create8x8FloatData(); - ReferenceDCT.Transpose8x8(expected); - - Buffer64 buffer = new Buffer64(); - buffer.LoadFrom(Create8x8FloatData()); - - buffer.TransposeInplace(); - - float[] actual = new float[64]; - buffer.CopyTo(actual); - - Assert.Equal(expected, actual); - - } - - [Fact] - public void TransposeInto() - { - float[] expected = Create8x8FloatData(); - ReferenceDCT.Transpose8x8(expected); - - Buffer64 source = new Buffer64(); - source.LoadFrom(Create8x8FloatData()); - - Buffer64 dest = new Buffer64(); - source.TranposeInto(ref dest); - - float[] actual = new float[64]; - dest.CopyTo(actual); - - Assert.Equal(expected, actual); - - } - - [Fact] - public void iDCT2D8x4_LeftPart() - { - float[] sourceArray = Create8x8FloatData(); - float[] expectedDestArray = new float[64]; - - ReferenceDCT.iDCT2D8x4_32f(sourceArray, expectedDestArray); - - Buffer64 source = new Buffer64(); - source.LoadFrom(sourceArray); - - Buffer64 dest = new Buffer64(); - - source.iDCT2D8x4_LeftPart(ref dest); - - float[] actualDestArray = new float[64]; - dest.CopyTo(actualDestArray); - - Print8x8Data(expectedDestArray); - Output.WriteLine("**************"); - Print8x8Data(actualDestArray); - - Assert.Equal(expectedDestArray, actualDestArray); - } - - [Fact] - public void iDCT2D8x4_RightPart() - { - Span sourceArray = Create8x8FloatData(); - Span expectedDestArray = new float[64]; - - ReferenceDCT.iDCT2D8x4_32f(sourceArray.Slice(4), expectedDestArray.Slice(4)); - - Buffer64 source = new Buffer64(); - source.LoadFrom(sourceArray); - - Buffer64 dest = new Buffer64(); - - source.iDCT2D8x4_RightPart(ref dest); - - float[] actualDestArray = new float[64]; - dest.CopyTo(actualDestArray); - - Print8x8Data(expectedDestArray); - Output.WriteLine("**************"); - Print8x8Data(actualDestArray); - - Assert.Equal(expectedDestArray.Data, actualDestArray); - } - - [Fact] - public void IDCT() - { - float[] sourceArray = Create8x8FloatData(); - float[] expectedDestArray = new float[64]; - float[] tempArray = new float[64]; - - ReferenceDCT.iDCT8x8_llm_sse(sourceArray, expectedDestArray, tempArray); - - Buffer64 source = new Buffer64(); - source.LoadFrom(sourceArray); - - Buffer64 dest = new Buffer64(); - Buffer64 tempBuffer = new Buffer64(); - - source.TransformIDCTInto(ref dest, ref tempBuffer); - - float[] actualDestArray = new float[64]; - dest.CopyTo(actualDestArray); - - Print8x8Data(expectedDestArray); - Output.WriteLine("**************"); - Print8x8Data(actualDestArray); - Assert.Equal(expectedDestArray, actualDestArray); - } - } -} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/Formats/Jpg/Buffer8x8Tests.cs b/tests/ImageSharp.Tests46/Formats/Jpg/Buffer8x8Tests.cs new file mode 100644 index 000000000..1b1508f09 --- /dev/null +++ b/tests/ImageSharp.Tests46/Formats/Jpg/Buffer8x8Tests.cs @@ -0,0 +1,379 @@ +using System; +using System.Diagnostics; +using System.Numerics; +using System.Runtime.CompilerServices; +using ImageSharp.Formats; +using Xunit; +using Xunit.Abstractions; + +namespace ImageSharp.Tests.Formats.Jpg +{ + // ReSharper disable once InconsistentNaming + public class Buffer8x8Tests : UtilityTestClassBase + { + public Buffer8x8Tests(ITestOutputHelper output) : base(output) + { + } + + [Theory] + [InlineData(1)] + [InlineData(1000000)] + public void Load_Store_FloatArray(int times) + { + + + float[] data = new float[Buffer8x8.ScalarCount]; + float[] mirror = new float[Buffer8x8.ScalarCount]; + + for (int i = 0; i < Buffer8x8.ScalarCount; i++) + { + data[i] = i; + } + Measure(times, () => + { + Buffer8x8 v = new Buffer8x8(); + v.LoadFrom(data); + v.CopyTo(mirror); + }); + + Assert.Equal(data, mirror); + PrintLinearData((Span)mirror); + } + + [Theory] + [InlineData(1)] + [InlineData(1000000)] + public void Load_Store_IntArray(int times) + { + + + int[] data = new int[Buffer8x8.ScalarCount]; + int[] mirror = new int[Buffer8x8.ScalarCount]; + + for (int i = 0; i < Buffer8x8.ScalarCount; i++) + { + data[i] = i; + } + Measure(times, () => + { + Buffer8x8 v = new Buffer8x8(); + v.LoadFrom(data); + v.CopyTo(mirror); + }); + + Assert.Equal(data, mirror); + PrintLinearData((Span)mirror); + } + + [Fact] + public void TransposeInplace() + { + float[] expected = Create8x8FloatData(); + ReferenceDCT.Transpose8x8(expected); + + Buffer8x8 buffer = new Buffer8x8(); + buffer.LoadFrom(Create8x8FloatData()); + + buffer.TransposeInplace(); + + float[] actual = new float[64]; + buffer.CopyTo(actual); + + Assert.Equal(expected, actual); + } + + [Fact] + public void TransposeInto() + { + float[] expected = Create8x8FloatData(); + ReferenceDCT.Transpose8x8(expected); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(Create8x8FloatData()); + + Buffer8x8 dest = new Buffer8x8(); + source.TranposeInto(ref dest); + + float[] actual = new float[64]; + dest.CopyTo(actual); + + Assert.Equal(expected, actual); + } + + [Fact] + public void TransposeIntoSafe() + { + float[] expected = Create8x8FloatData(); + ReferenceDCT.Transpose8x8(expected); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(Create8x8FloatData()); + + Buffer8x8 dest = new Buffer8x8(); + source.TransposeIntoSafe(ref dest); + + float[] actual = new float[64]; + dest.CopyTo(actual); + + Assert.Equal(expected, actual); + } + + [Fact] + public unsafe void PinnedTransposeInto() + { + float[] expected = Create8x8FloatData(); + ReferenceDCT.Transpose8x8(expected); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(Create8x8FloatData()); + + Buffer8x8 dest = new Buffer8x8(); + + Buffer8x8* sPtr = &source; + Buffer8x8* dPtr = &dest; + + Buffer8x8.PinnedTransposeInto(sPtr, dPtr); + + float[] actual = new float[64]; + dest.CopyTo(actual); + + Assert.Equal(expected, actual); + } + + private class BufferHolder + { + public Buffer8x8 Buffer; + } + + [Theory] + [InlineData(1)] + [InlineData(10000000)] + public void TransposeInto_Benchmark(int times) + { + BufferHolder source = new BufferHolder(); + source.Buffer.LoadFrom(Create8x8FloatData()); + BufferHolder dest = new BufferHolder(); + + Output.WriteLine($"TransposeInto_Benchmark X {times} ..."); + Stopwatch sw = Stopwatch.StartNew(); + + for (int i = 0; i < times; i++) + { + source.Buffer.TranposeInto(ref dest.Buffer); + } + + sw.Stop(); + Output.WriteLine($"TransposeInto_Benchmark finished in {sw.ElapsedMilliseconds} ms"); + } + + [Theory] + [InlineData(1)] + [InlineData(10000000)] + public unsafe void PinnedTransposeInto_Benchmark(int times) + { + BufferHolder source = new BufferHolder(); + source.Buffer.LoadFrom(Create8x8FloatData()); + BufferHolder dest = new BufferHolder(); + + fixed (Buffer8x8* sPtr = &source.Buffer) + { + fixed (Buffer8x8* dPtr = &dest.Buffer) + { + Output.WriteLine($"PinnedTransposeInto_Benchmark X {times} ..."); + Stopwatch sw = Stopwatch.StartNew(); + + for (int i = 0; i < times; i++) + { + Buffer8x8.PinnedTransposeInto(sPtr, dPtr); + } + + sw.Stop(); + Output.WriteLine($"PinnedTransposeInto_Benchmark finished in {sw.ElapsedMilliseconds} ms"); + } + } + + } + + + [Fact] + public void iDCT2D8x4_LeftPart() + { + float[] sourceArray = Create8x8FloatData(); + float[] expectedDestArray = new float[64]; + + ReferenceDCT.iDCT2D8x4_32f(sourceArray, expectedDestArray); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(sourceArray); + + Buffer8x8 dest = new Buffer8x8(); + + source.iDCT2D8x4_LeftPart(ref dest); + + float[] actualDestArray = new float[64]; + dest.CopyTo(actualDestArray); + + Print8x8Data(expectedDestArray); + Output.WriteLine("**************"); + Print8x8Data(actualDestArray); + + Assert.Equal(expectedDestArray, actualDestArray); + } + + [Fact] + public void iDCT2D8x4_RightPart() + { + Span sourceArray = Create8x8FloatData(); + Span expectedDestArray = new float[64]; + + ReferenceDCT.iDCT2D8x4_32f(sourceArray.Slice(4), expectedDestArray.Slice(4)); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(sourceArray); + + Buffer8x8 dest = new Buffer8x8(); + + source.iDCT2D8x4_RightPart(ref dest); + + float[] actualDestArray = new float[64]; + dest.CopyTo(actualDestArray); + + Print8x8Data(expectedDestArray); + Output.WriteLine("**************"); + Print8x8Data(actualDestArray); + + Assert.Equal(expectedDestArray.Data, actualDestArray); + } + + [Fact] + public void IDCT() + { + float[] sourceArray = Create8x8FloatData(); + float[] expectedDestArray = new float[64]; + float[] tempArray = new float[64]; + + ReferenceDCT.iDCT8x8_llm_sse(sourceArray, expectedDestArray, tempArray); + + Buffer8x8 source = new Buffer8x8(); + source.LoadFrom(sourceArray); + + Buffer8x8 dest = new Buffer8x8(); + Buffer8x8 tempBuffer = new Buffer8x8(); + + source.TransformIDCTInto(ref dest, ref tempBuffer); + + float[] actualDestArray = new float[64]; + dest.CopyTo(actualDestArray); + + Print8x8Data(expectedDestArray); + Output.WriteLine("**************"); + Print8x8Data(actualDestArray); + Assert.Equal(expectedDestArray, actualDestArray); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void TransposeMatrix(ref Matrix4x4 s, ref Matrix4x4 d) + { + d.M11 = s.M11; + d.M12 = s.M21; + d.M13 = s.M31; + d.M14 = s.M41; + d.M21 = s.M12; + d.M22 = s.M22; + d.M23 = s.M32; + d.M24 = s.M42; + d.M31 = s.M13; + d.M32 = s.M23; + d.M33 = s.M33; + d.M34 = s.M43; + d.M41 = s.M14; + d.M42 = s.M24; + d.M43 = s.M34; + d.M44 = s.M44; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe void TransposeMatrixPtr(float* s, float* d) + { + for (int i = 0; i < 4; i++) + { + int i4 = i*4; + for (int j = 0; j < 4; j++) + { + d[j*4 + i] = s[i4 + j]; + } + } + } + + + + + [Theory] + [InlineData(50000000)] + public void TransposeMatrix_Custom(int times) + { + Matrix4x4 s = new Matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Matrix4x4 d = new Matrix4x4(); + + Output.WriteLine($"TransposeMatrix_System X {times} ..."); + Stopwatch sw = Stopwatch.StartNew(); + + for (int i = 0; i < times; i++) + { + TransposeMatrix(ref s, ref d); + } + + sw.Stop(); + Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms"); + + Output.WriteLine(d.ToString()); + } + + + + [Theory] + [InlineData(50000000)] + public unsafe void TransposeMatrix_System(int times) + { + Matrix4x4 s = new Matrix4x4(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16); + Matrix4x4 d = new Matrix4x4(); + + Output.WriteLine($"TransposeMatrix_System X {times} ..."); + Stopwatch sw = Stopwatch.StartNew(); + + for (int i = 0; i < times; i++) + { + d = Matrix4x4.Transpose(s); + } + + sw.Stop(); + Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms"); + + Output.WriteLine(d.ToString()); + } + + [Theory] + [InlineData(50000000)] + public unsafe void TransposeMatrix_Ptr(int times) + { + Matrix4x4 s = new Matrix4x4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16); + Matrix4x4 d = new Matrix4x4(); + + float* sPtr = (float*) &s; + float* dPtr = (float*) &d; + + Output.WriteLine($"TransposeMatrix_System X {times} ..."); + Stopwatch sw = Stopwatch.StartNew(); + + for (int i = 0; i < times; i++) + { + TransposeMatrixPtr(sPtr,dPtr); + } + + sw.Stop(); + Output.WriteLine($"TransposeMatrix_System finished in {sw.ElapsedMilliseconds} ms"); + + Output.WriteLine(d.ToString()); + } + } +} \ No newline at end of file diff --git a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj b/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj index 07b7cf407..7f571cd70 100644 --- a/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj +++ b/tests/ImageSharp.Tests46/ImageSharp.Tests46.csproj @@ -74,7 +74,7 @@ - +