Browse Source

Merge pull request #1390 from SixLabors/js/block8x8f-optimizations

Optimize Block8x8F low hanging fruit and fix naming
js/color-alpha-handling
James Jackson-South 5 years ago
committed by GitHub
parent
commit
f27c678df2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 6
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs
  2. 6
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt
  3. 203
      src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs
  4. 4
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
  5. 6
      src/ImageSharp/Formats/Jpeg/Components/FastFloatingPointDCT.cs
  6. 21
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs
  7. 37
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs
  8. 21
      tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs
  9. 160
      tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs
  10. 3
      tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs

6
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.cs

@ -13,7 +13,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Level shift by +maximum/2, clip to [0, maximum]
/// </summary>
public void NormalizeColorsInplace(float maximum)
public void NormalizeColorsInPlace(float maximum)
{
var CMin4 = new Vector4(0F);
var CMax4 = new Vector4(maximum);
@ -38,10 +38,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
/// <summary>
/// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step.
/// AVX2-only variant for executing <see cref="NormalizeColorsInPlace"/> and <see cref="RoundInPlace"/> in one step.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceVector8(float maximum)
public void NormalizeColorsAndRoundInPlaceVector8(float maximum)
{
var off = new Vector<float>(MathF.Ceiling(maximum / 2));
var max = new Vector<float>(maximum);

6
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.Generated.tt

@ -26,7 +26,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Level shift by +maximum/2, clip to [0, maximum]
/// </summary>
public void NormalizeColorsInplace(float maximum)
public void NormalizeColorsInPlace(float maximum)
{
var CMin4 = new Vector4(0F);
var CMax4 = new Vector4(maximum);
@ -49,10 +49,10 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
}
/// <summary>
/// AVX2-only variant for executing <see cref="NormalizeColorsInplace"/> and <see cref="RoundInplace"/> in one step.
/// AVX2-only variant for executing <see cref="NormalizeColorsInPlace"/> and <see cref="RoundInPlace"/> in one step.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public void NormalizeColorsAndRoundInplaceVector8(float maximum)
public void NormalizeColorsAndRoundInPlaceVector8(float maximum)
{
var off = new Vector<float>(MathF.Ceiling(maximum / 2));
var max = new Vector<float>(maximum);

203
src/ImageSharp/Formats/Jpeg/Components/Block8x8F.cs

@ -281,73 +281,156 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// </summary>
/// <param name="value">The value to multiply by.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public void MultiplyInplace(float value)
{
this.V0L *= value;
this.V0R *= value;
this.V1L *= value;
this.V1R *= value;
this.V2L *= value;
this.V2R *= value;
this.V3L *= value;
this.V3R *= value;
this.V4L *= value;
this.V4R *= value;
this.V5L *= value;
this.V5R *= value;
this.V6L *= value;
this.V6R *= value;
this.V7L *= value;
this.V7R *= value;
public void MultiplyInPlace(float value)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
var valueVec = Vector256.Create(value);
Unsafe.As<Vector4, Vector256<float>>(ref this.V0L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V0L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V1L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V1L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V2L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V2L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V3L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V3L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V4L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V4L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V5L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V5L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V6L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V6L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V7L) = Avx.Multiply(Unsafe.As<Vector4, Vector256<float>>(ref this.V7L), valueVec);
}
else
#endif
{
var valueVec = new Vector4(value);
this.V0L *= valueVec;
this.V0R *= valueVec;
this.V1L *= valueVec;
this.V1R *= valueVec;
this.V2L *= valueVec;
this.V2R *= valueVec;
this.V3L *= valueVec;
this.V3R *= valueVec;
this.V4L *= valueVec;
this.V4R *= valueVec;
this.V5L *= valueVec;
this.V5R *= valueVec;
this.V6L *= valueVec;
this.V6R *= valueVec;
this.V7L *= valueVec;
this.V7R *= valueVec;
}
}
/// <summary>
/// Multiply all elements of the block by the corresponding elements of 'other'.
/// </summary>
[MethodImpl(InliningOptions.ShortMethod)]
public void MultiplyInplace(ref Block8x8F other)
{
this.V0L *= other.V0L;
this.V0R *= other.V0R;
this.V1L *= other.V1L;
this.V1R *= other.V1R;
this.V2L *= other.V2L;
this.V2R *= other.V2R;
this.V3L *= other.V3L;
this.V3R *= other.V3R;
this.V4L *= other.V4L;
this.V4R *= other.V4R;
this.V5L *= other.V5L;
this.V5R *= other.V5R;
this.V6L *= other.V6L;
this.V6R *= other.V6R;
this.V7L *= other.V7L;
this.V7R *= other.V7R;
public unsafe void MultiplyInPlace(ref Block8x8F other)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
Unsafe.As<Vector4, Vector256<float>>(ref this.V0L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V0L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V0L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V1L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V1L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V1L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V2L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V2L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V2L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V3L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V3L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V3L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V4L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V4L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V4L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V5L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V5L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V5L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V6L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V6L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V6L));
Unsafe.As<Vector4, Vector256<float>>(ref this.V7L)
= Avx.Multiply(
Unsafe.As<Vector4, Vector256<float>>(ref this.V7L),
Unsafe.As<Vector4, Vector256<float>>(ref other.V7L));
}
else
#endif
{
this.V0L *= other.V0L;
this.V0R *= other.V0R;
this.V1L *= other.V1L;
this.V1R *= other.V1R;
this.V2L *= other.V2L;
this.V2R *= other.V2R;
this.V3L *= other.V3L;
this.V3R *= other.V3R;
this.V4L *= other.V4L;
this.V4R *= other.V4R;
this.V5L *= other.V5L;
this.V5R *= other.V5R;
this.V6L *= other.V6L;
this.V6R *= other.V6R;
this.V7L *= other.V7L;
this.V7R *= other.V7R;
}
}
/// <summary>
/// Adds a vector to all elements of the block.
/// </summary>
/// <param name="diff">The added vector</param>
/// <param name="value">The added vector.</param>
[MethodImpl(InliningOptions.ShortMethod)]
public void AddToAllInplace(Vector4 diff)
{
this.V0L += diff;
this.V0R += diff;
this.V1L += diff;
this.V1R += diff;
this.V2L += diff;
this.V2R += diff;
this.V3L += diff;
this.V3R += diff;
this.V4L += diff;
this.V4R += diff;
this.V5L += diff;
this.V5R += diff;
this.V6L += diff;
this.V6R += diff;
this.V7L += diff;
this.V7R += diff;
public void AddInPlace(float value)
{
#if SUPPORTS_RUNTIME_INTRINSICS
if (Avx.IsSupported)
{
var valueVec = Vector256.Create(value);
Unsafe.As<Vector4, Vector256<float>>(ref this.V0L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V0L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V1L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V1L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V2L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V2L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V3L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V3L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V4L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V4L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V5L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V5L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V6L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V6L), valueVec);
Unsafe.As<Vector4, Vector256<float>>(ref this.V7L) = Avx.Add(Unsafe.As<Vector4, Vector256<float>>(ref this.V7L), valueVec);
}
else
#endif
{
var valueVec = new Vector4(value);
this.V0L += valueVec;
this.V0R += valueVec;
this.V1L += valueVec;
this.V1R += valueVec;
this.V2L += valueVec;
this.V2R += valueVec;
this.V3L += valueVec;
this.V3R += valueVec;
this.V4L += valueVec;
this.V4R += valueVec;
this.V5L += valueVec;
this.V5R += valueVec;
this.V6L += valueVec;
this.V6R += valueVec;
this.V7L += valueVec;
this.V7R += valueVec;
}
}
/// <summary>
@ -468,23 +551,23 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
/// <summary>
/// Level shift by +maximum/2, clip to [0..maximum], and round all the values in the block.
/// </summary>
public void NormalizeColorsAndRoundInplace(float maximum)
public void NormalizeColorsAndRoundInPlace(float maximum)
{
if (SimdUtils.HasVector8)
{
this.NormalizeColorsAndRoundInplaceVector8(maximum);
this.NormalizeColorsAndRoundInPlaceVector8(maximum);
}
else
{
this.NormalizeColorsInplace(maximum);
this.RoundInplace();
this.NormalizeColorsInPlace(maximum);
this.RoundInPlace();
}
}
/// <summary>
/// Rounds all values in the block.
/// </summary>
public void RoundInplace()
public void RoundInPlace()
{
for (int i = 0; i < Size; i++)
{

4
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs

@ -81,14 +81,14 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
b.LoadFrom(ref sourceBlock);
// Dequantize:
b.MultiplyInplace(ref this.DequantiazationTable);
b.MultiplyInPlace(ref this.DequantiazationTable);
FastFloatingPointDCT.TransformIDCT(ref b, ref this.WorkspaceBlock1, ref this.WorkspaceBlock2);
// To conform better to libjpeg we actually NEED TO loose precision here.
// This is because they store blocks as Int16 between all the operations.
// To be "more accurate", we need to emulate this by rounding!
this.WorkspaceBlock1.NormalizeColorsAndRoundInplace(maximumValue);
this.WorkspaceBlock1.NormalizeColorsAndRoundInPlace(maximumValue);
this.WorkspaceBlock1.ScaledCopyTo(
ref destAreaOrigin,

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

@ -61,7 +61,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
IDCT8x4_RightPart(ref temp, ref dest);
// TODO: What if we leave the blocks in a scaled-by-x8 state until final color packing?
dest.MultiplyInplace(C_0_125);
dest.MultiplyInPlace(C_0_125);
}
/// <summary>
@ -324,7 +324,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
src.TransposeInto(ref temp);
if (offsetSourceByNeg128)
{
temp.AddToAllInplace(new Vector4(-128));
temp.AddInPlace(-128F);
}
FDCT8x4_LeftPart(ref temp, ref dest);
@ -335,7 +335,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components
FDCT8x4_LeftPart(ref temp, ref dest);
FDCT8x4_RightPart(ref temp, ref dest);
dest.MultiplyInplace(C_0_125);
dest.MultiplyInPlace(C_0_125);
}
}
}

21
tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_AddInPlace.cs

@ -0,0 +1,21 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations
{
[Config(typeof(Config.HwIntrinsics_SSE_AVX))]
public class Block8x8F_AddInPlace
{
[Benchmark]
public float AddInplace()
{
float f = 42F;
Block8x8F b = default;
b.AddInPlace(f);
return f;
}
}
}

37
tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceBlock.cs

@ -0,0 +1,37 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations
{
[Config(typeof(Config.HwIntrinsics_SSE_AVX))]
public class Block8x8F_MultiplyInPlaceBlock
{
private static readonly Block8x8F Source = Create8x8FloatData();
[Benchmark]
public void MultiplyInPlaceBlock()
{
Block8x8F dest = default;
Source.MultiplyInPlace(ref dest);
}
private static Block8x8F Create8x8FloatData()
{
var result = new float[64];
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
result[(i * 8) + j] = (i * 10) + j;
}
}
var source = default(Block8x8F);
source.LoadFrom(result);
return source;
}
}
}

21
tests/ImageSharp.Benchmarks/Codecs/Jpeg/BlockOperations/Block8x8F_MultiplyInPlaceScalar.cs

@ -0,0 +1,21 @@
// Copyright (c) Six Labors.
// Licensed under the Apache License, Version 2.0.
using BenchmarkDotNet.Attributes;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
namespace SixLabors.ImageSharp.Benchmarks.Codecs.Jpeg.BlockOperations
{
[Config(typeof(Config.HwIntrinsics_SSE_AVX))]
public class Block8x8F_MultiplyInPlaceScalar
{
[Benchmark]
public float MultiplyInPlaceScalar()
{
float f = 42F;
Block8x8F b = default;
b.MultiplyInPlace(f);
return f;
}
}
}

160
tests/ImageSharp.Tests/Formats/Jpg/Block8x8FTests.cs

@ -5,6 +5,7 @@
// #define BENCHMARKING
using System;
using System.Diagnostics;
using SixLabors.ImageSharp.Formats.Jpeg.Components;
using SixLabors.ImageSharp.Tests.Formats.Jpg.Utils;
using SixLabors.ImageSharp.Tests.TestUtilities;
@ -44,20 +45,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Measure(
Times,
() =>
{
var block = default(Block8x8F);
for (int i = 0; i < Block8x8F.Size; i++)
{
var block = default(Block8x8F);
for (int i = 0; i < Block8x8F.Size; i++)
{
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8F.Size; i++)
{
sum += block[i];
}
});
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8F.Size; i++)
{
sum += block[i];
}
});
Assert.Equal(sum, 64f * 63f * 0.5f);
}
@ -69,20 +70,20 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Measure(
Times,
() =>
{
// Block8x8F block = new Block8x8F();
float[] block = new float[64];
for (int i = 0; i < Block8x8F.Size; i++)
{
// Block8x8F block = new Block8x8F();
float[] block = new float[64];
for (int i = 0; i < Block8x8F.Size; i++)
{
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8F.Size; i++)
{
sum += block[i];
}
});
block[i] = i;
}
sum = 0;
for (int i = 0; i < Block8x8F.Size; i++)
{
sum += block[i];
}
});
Assert.Equal(sum, 64f * 63f * 0.5f);
}
@ -100,11 +101,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Measure(
Times,
() =>
{
var b = default(Block8x8F);
b.LoadFrom(data);
b.ScaledCopyTo(mirror);
});
{
var b = default(Block8x8F);
b.LoadFrom(data);
b.ScaledCopyTo(mirror);
});
Assert.Equal(data, mirror);
@ -125,11 +126,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Measure(
Times,
() =>
{
var b = default(Block8x8F);
Block8x8F.LoadFrom(&b, data);
Block8x8F.ScaledCopyTo(&b, mirror);
});
{
var b = default(Block8x8F);
Block8x8F.LoadFrom(&b, data);
Block8x8F.ScaledCopyTo(&b, mirror);
});
Assert.Equal(data, mirror);
@ -150,11 +151,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Measure(
Times,
() =>
{
var v = default(Block8x8F);
v.LoadFrom(data);
v.ScaledCopyTo(mirror);
});
{
var v = default(Block8x8F);
v.LoadFrom(data);
v.ScaledCopyTo(mirror);
});
Assert.Equal(data, mirror);
@ -234,7 +235,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.PrintLinearData(input);
Block8x8F dest = block;
dest.NormalizeColorsInplace(255);
dest.NormalizeColorsInPlace(255);
float[] array = new float[64];
dest.ScaledCopyTo(array);
@ -259,11 +260,11 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
Block8x8F source = CreateRandomFloatBlock(-200, 200, seed);
Block8x8F expected = source;
expected.NormalizeColorsInplace(255);
expected.RoundInplace();
expected.NormalizeColorsInPlace(255);
expected.RoundInPlace();
Block8x8F actual = source;
actual.NormalizeColorsAndRoundInplaceVector8(255);
actual.NormalizeColorsAndRoundInPlaceVector8(255);
this.Output.WriteLine(expected.ToString());
this.Output.WriteLine(actual.ToString());
@ -324,12 +325,12 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
[InlineData(1)]
[InlineData(2)]
[InlineData(3)]
public void RoundInplaceSlow(int seed)
public void RoundInPlaceSlow(int seed)
{
Block8x8F s = CreateRandomFloatBlock(-500, 500, seed);
Block8x8F d = s;
d.RoundInplace();
d.RoundInPlace();
this.Output.WriteLine(s.ToString());
this.Output.WriteLine(d.ToString());
@ -344,19 +345,26 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
[Fact]
public void MultiplyInplace_ByOtherBlock()
public void MultiplyInPlace_ByOtherBlock()
{
Block8x8F original = CreateRandomFloatBlock(-500, 500, 42);
Block8x8F m = CreateRandomFloatBlock(-500, 500, 42);
static void RunTest()
{
Block8x8F original = CreateRandomFloatBlock(-500, 500, 42);
Block8x8F m = CreateRandomFloatBlock(-500, 500, 42);
Block8x8F actual = original;
Block8x8F actual = original;
actual.MultiplyInplace(ref m);
actual.MultiplyInPlace(ref m);
for (int i = 0; i < Block8x8F.Size; i++)
{
Assert.Equal(original[i] * m[i], actual[i]);
for (int i = 0; i < Block8x8F.Size; i++)
{
Assert.Equal(original[i] * m[i], actual[i]);
}
}
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX);
}
[Theory]
@ -396,23 +404,51 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
ReferenceImplementations.DequantizeBlock(&expected, &qt, unzig.Data);
actual.MultiplyInplace(ref zigQt);
actual.MultiplyInPlace(ref zigQt);
this.CompareBlocks(expected, actual, 0);
}
[Fact]
public void MultiplyInplace_ByScalar()
public void AddToAllInPlace()
{
Block8x8F original = CreateRandomFloatBlock(-500, 500);
static void RunTest()
{
Block8x8F original = CreateRandomFloatBlock(-500, 500);
Block8x8F actual = original;
actual.MultiplyInplace(42f);
Block8x8F actual = original;
actual.AddInPlace(42f);
for (int i = 0; i < 64; i++)
for (int i = 0; i < 64; i++)
{
Assert.Equal(original[i] + 42f, actual[i]);
}
}
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX);
}
[Fact]
public void MultiplyInPlace_ByScalar()
{
static void RunTest()
{
Assert.Equal(original[i] * 42f, actual[i]);
Block8x8F original = CreateRandomFloatBlock(-500, 500);
Block8x8F actual = original;
actual.MultiplyInPlace(42f);
for (int i = 0; i < 64; i++)
{
Assert.Equal(original[i] * 42f, actual[i]);
}
}
FeatureTestRunner.RunWithHwIntrinsicsFeature(
RunTest,
HwIntrinsics.AllowAll | HwIntrinsics.DisableAVX);
}
[Fact]

3
tests/ImageSharp.Tests/Formats/Jpg/JpegDecoderTests.Progressive.cs

@ -54,8 +54,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
RemoteExecutor.Invoke(
RunTest,
providerDump,
"Disco")
.Dispose();
"Disco").Dispose();
}
}
}

Loading…
Cancel
Save