Browse Source

Added DCT tests

pull/1632/head
Dmitry Pentin 5 years ago
parent
commit
a4222fd91c
  1. 2
      src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs
  2. 207
      tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

2
src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs

@ -203,7 +203,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// </summary> /// </summary>
/// <param name="s">Source</param> /// <param name="s">Source</param>
/// <param name="d">Destination</param> /// <param name="d">Destination</param>
private static void FDCT8x8_Avx(ref Block8x8F s, ref Block8x8F d) public static void FDCT8x8_Avx(ref Block8x8F s, ref Block8x8F d)
{ {
#if SUPPORTS_RUNTIME_INTRINSICS #if SUPPORTS_RUNTIME_INTRINSICS
Debug.Assert(Avx.IsSupported, "AVX is required to execute this method"); Debug.Assert(Avx.IsSupported, "AVX is required to execute this method");

207
tests/ImageSharp.Tests/Formats/Jpg/DCTTests.cs

@ -2,7 +2,7 @@
// Licensed under the Apache License, Version 2.0. // Licensed under the Apache License, Version 2.0.
using System; using System;
using System.Runtime.Intrinsics.X86;
using SixLabors.ImageSharp.Formats.Jpeg.Components; using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils; using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils;
@ -22,94 +22,160 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
{ {
} }
[Fact] // Reference tests
public void IDCT2D8x4_LeftPart() [Theory]
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void LLM_TransformIDCT_CompareToNonOptimized(int seed)
{ {
float[] sourceArray = Create8x8FloatData(); float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed);
var expectedDestArray = new float[64];
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(sourceArray, expectedDestArray); var source = Block8x8F.Load(sourceArray);
var source = default(Block8x8F); Block8x8F expected = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformIDCT(ref source);
source.LoadFrom(sourceArray);
var dest = default(Block8x8F); var temp = default(Block8x8F);
var actual = default(Block8x8F);
FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp);
FastFloatingPointDCT.IDCT8x4_LeftPart(ref source, ref dest); this.CompareBlocks(expected, actual, 1f);
}
var actualDestArray = new float[64]; [Theory]
dest.ScaledCopyTo(actualDestArray); [InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void LLM_TransformIDCT_CompareToAccurate(int seed)
{
float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed);
var source = Block8x8F.Load(sourceArray);
Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref source);
this.Print8x8Data(expectedDestArray); var temp = default(Block8x8F);
this.Output.WriteLine("**************"); var actual = default(Block8x8F);
this.Print8x8Data(actualDestArray); FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp);
Assert.Equal(expectedDestArray, actualDestArray); this.CompareBlocks(expected, actual, 1f);
} }
[Fact]
public void IDCT2D8x4_RightPart() // Inverse transform
[Theory]
[InlineData(1)]
[InlineData(2)]
public void IDCT8x4_LeftPart(int seed)
{ {
float[] sourceArray = Create8x8FloatData(); Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var expectedDestArray = new float[64]; var srcBlock = default(Block8x8F);
srcBlock.LoadFrom(src);
var destBlock = default(Block8x8F);
var expectedDest = new float[64];
// reference
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(src, expectedDest);
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(sourceArray.AsSpan(4), expectedDestArray.AsSpan(4)); // testee
FastFloatingPointDCT.IDCT8x4_LeftPart(ref srcBlock, ref destBlock);
var actualDest = new float[64];
destBlock.ScaledCopyTo(actualDest);
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
}
[Theory]
[InlineData(1)]
[InlineData(2)]
public void IDCT8x4_RightPart(int seed)
{
Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var srcBlock = default(Block8x8F);
srcBlock.LoadFrom(src);
var source = default(Block8x8F); var destBlock = default(Block8x8F);
source.LoadFrom(sourceArray);
var dest = default(Block8x8F); var expectedDest = new float[64];
FastFloatingPointDCT.IDCT8x4_RightPart(ref source, ref dest); // reference
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan(4));
var actualDestArray = new float[64]; // testee
dest.ScaledCopyTo(actualDestArray); FastFloatingPointDCT.IDCT8x4_RightPart(ref srcBlock, ref destBlock);
this.Print8x8Data(expectedDestArray); var actualDest = new float[64];
this.Output.WriteLine("**************"); destBlock.ScaledCopyTo(actualDest);
this.Print8x8Data(actualDestArray);
Assert.Equal(expectedDestArray, actualDestArray); Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
} }
[Theory] [Theory]
[InlineData(1)] [InlineData(1)]
[InlineData(2)] [InlineData(2)]
[InlineData(3)] public void IDCT8x8_Avx(int seed)
public void LLM_TransformIDCT_CompareToNonOptimized(int seed)
{ {
float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed); if (!Avx.IsSupported)
{
this.Output.WriteLine("No AVX present, skipping test!");
return;
}
var source = Block8x8F.Load(sourceArray); Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var srcBlock = default(Block8x8F);
srcBlock.LoadFrom(src);
Block8x8F expected = ReferenceImplementations.LLM_FloatingPoint_DCT.TransformIDCT(ref source); var destBlock = default(Block8x8F);
var temp = default(Block8x8F); var expectedDest = new float[64];
var actual = default(Block8x8F);
FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp);
this.CompareBlocks(expected, actual, 1f); // reference, left part
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(src, expectedDest);
// reference, right part
ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan(4));
// testee, whole 8x8
FastFloatingPointDCT.IDCT8x8_Avx(ref srcBlock, ref destBlock);
var actualDest = new float[64];
destBlock.ScaledCopyTo(actualDest);
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
} }
[Theory] [Theory]
[InlineData(1)] [InlineData(1)]
[InlineData(2)] [InlineData(2)]
[InlineData(3)] public void TransformIDCT(int seed)
public void LLM_TransformIDCT_CompareToAccurate(int seed)
{ {
float[] sourceArray = Create8x8RoundedRandomFloatData(-1000, 1000, seed); Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var srcBlock = default(Block8x8F);
srcBlock.LoadFrom(src);
var source = Block8x8F.Load(sourceArray); var destBlock = default(Block8x8F);
Block8x8F expected = ReferenceImplementations.AccurateDCT.TransformIDCT(ref source); var expectedDest = new float[64];
var temp1 = new float[64];
var temp2 = default(Block8x8F);
var temp = default(Block8x8F); // reference
var actual = default(Block8x8F); ReferenceImplementations.LLM_FloatingPoint_DCT.IDCT2D_llm(src, expectedDest, temp1);
FastFloatingPointDCT.TransformIDCT(ref source, ref actual, ref temp);
this.CompareBlocks(expected, actual, 1f); // testee
FastFloatingPointDCT.TransformIDCT(ref srcBlock, ref destBlock, ref temp2);
var actualDest = new float[64];
destBlock.ScaledCopyTo(actualDest);
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
} }
// Forward transform
[Theory] [Theory]
[InlineData(1)] [InlineData(1)]
[InlineData(2)] [InlineData(2)]
@ -123,7 +189,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var expectedDest = new float[64]; var expectedDest = new float[64];
// reference
ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src, expectedDest); ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src, expectedDest);
// testee
FastFloatingPointDCT.FDCT8x4_LeftPart(ref srcBlock, ref destBlock); FastFloatingPointDCT.FDCT8x4_LeftPart(ref srcBlock, ref destBlock);
var actualDest = new float[64]; var actualDest = new float[64];
@ -145,7 +214,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var expectedDest = new float[64]; var expectedDest = new float[64];
// reference
ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan(4)); ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan(4));
// testee
FastFloatingPointDCT.FDCT8x4_RightPart(ref srcBlock, ref destBlock); FastFloatingPointDCT.FDCT8x4_RightPart(ref srcBlock, ref destBlock);
var actualDest = new float[64]; var actualDest = new float[64];
@ -154,6 +226,40 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f)); Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
} }
[Theory]
[InlineData(1)]
[InlineData(2)]
public void FDCT8x8_Avx(int seed)
{
if (!Avx.IsSupported)
{
this.Output.WriteLine("No AVX present, skipping test!");
return;
}
Span<float> src = Create8x8RoundedRandomFloatData(-200, 200, seed);
var srcBlock = default(Block8x8F);
srcBlock.LoadFrom(src);
var destBlock = default(Block8x8F);
var expectedDest = new float[64];
// reference, left part
ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src, expectedDest);
// reference, right part
ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D8x4_32f(src.Slice(4), expectedDest.AsSpan(4));
// testee, whole 8x8
FastFloatingPointDCT.FDCT8x8_Avx(ref srcBlock, ref destBlock);
var actualDest = new float[64];
destBlock.ScaledCopyTo(actualDest);
Assert.Equal(actualDest, expectedDest, new ApproximateFloatComparer(1f));
}
[Theory] [Theory]
[InlineData(1)] [InlineData(1)]
[InlineData(2)] [InlineData(2)]
@ -169,7 +275,10 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
var temp1 = new float[64]; var temp1 = new float[64];
var temp2 = default(Block8x8F); var temp2 = default(Block8x8F);
// reference
ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D_llm(src, expectedDest, temp1, downscaleBy8: true); ReferenceImplementations.LLM_FloatingPoint_DCT.FDCT2D_llm(src, expectedDest, temp1, downscaleBy8: true);
// testee
FastFloatingPointDCT.TransformFDCT(ref srcBlock, ref destBlock, ref temp2, false); FastFloatingPointDCT.TransformFDCT(ref srcBlock, ref destBlock, ref temp2, false);
var actualDest = new float[64]; var actualDest = new float[64];

Loading…
Cancel
Save