Browse Source

Faster Pow functions

pull/595/head
James Jackson-South 8 years ago
parent
commit
2c3dc41eac
  1. 6
      src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLabToCieXyzConverter.cs
  2. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuvToCieXyzConverter.cs
  3. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs
  4. 2
      src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs
  5. 32
      src/ImageSharp/Common/Helpers/ImageMaths.cs
  6. 2
      tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj
  7. 3
      tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs
  8. 39
      tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs
  9. 2
      tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

6
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLabToCieXyzConverter.cs

@ -24,11 +24,11 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
float fx = (a / 500F) + fy;
float fz = fy - (b / 200F);
float fx3 = MathF.Pow(fx, 3F);
float fz3 = MathF.Pow(fz, 3F);
float fx3 = ImageMaths.Pow3(fx);
float fz3 = ImageMaths.Pow3(fz);
float xr = fx3 > CieConstants.Epsilon ? fx3 : ((116F * fx) - 16F) / CieConstants.Kappa;
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? MathF.Pow((l + 16F) / 116F, 3F) : l / CieConstants.Kappa;
float yr = l > CieConstants.Kappa * CieConstants.Epsilon ? ImageMaths.Pow3((l + 16F) / 116F) : l / CieConstants.Kappa;
float zr = fz3 > CieConstants.Epsilon ? fz3 : ((116F * fz) - 16F) / CieConstants.Kappa;
var wxyz = new Vector3(input.WhitePoint.X, input.WhitePoint.Y, input.WhitePoint.Z);

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/CieLuvToCieXyzConverter.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
float v0 = ComputeV0(input.WhitePoint);
float y = l > CieConstants.Kappa * CieConstants.Epsilon
? MathF.Pow((l + 16) / 116, 3)
? ImageMaths.Pow3((l + 16) / 116)
: l / CieConstants.Kappa;
float a = ((52 * l / (u + (13 * l * u0))) - 1) / 3;

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/HunterLabToCieXyzConverter.cs

@ -24,7 +24,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
float ka = ComputeKa(input.WhitePoint);
float kb = ComputeKb(input.WhitePoint);
float y = MathF.Pow(l / 100F, 2) * yn;
float y = ImageMaths.Pow2(l / 100F) * yn;
float x = (((a / ka) * MathF.Sqrt(y / yn)) + (y / yn)) * xn;
float z = (((b / kb) * MathF.Sqrt(y / yn)) - (y / yn)) * (-zn);

2
src/ImageSharp/ColorSpaces/Conversion/Implementation/LCompanding.cs

@ -20,7 +20,7 @@ namespace SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Expand(float channel)
{
return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : MathF.Pow((channel + 0.16F) / 1.16F, 3);
return channel <= 0.08 ? 100 * channel / CieConstants.Kappa : ImageMaths.Pow3((channel + 0.16F) / 1.16F);
}
/// <inheritdoc/>

32
src/ImageSharp/Common/Helpers/ImageMaths.cs

@ -29,6 +29,22 @@ namespace SixLabors.ImageSharp
return (x ^ y) - y;
}
/// <summary>
/// Returns a specified number raised to the power of 2
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 2.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Pow2(float x) => x * x;
/// <summary>
/// Returns a specified number raised to the power of 3
/// </summary>
/// <param name="x">A single-precision floating-point number</param>
/// <returns>The number <paramref name="x" /> raised to the power of 3.</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float Pow3(float x) => x * x * x;
/// <summary>
/// Returns how many bits are required to store the specified number of colors.
/// Performs a Log2() on the value.
@ -38,10 +54,7 @@ namespace SixLabors.ImageSharp
/// The <see cref="int"/>
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetBitsNeededForColorDepth(int colors)
{
return (int)Math.Ceiling(Math.Log(colors, 2));
}
public static int GetBitsNeededForColorDepth(int colors) => (int)Math.Ceiling(Math.Log(colors, 2));
/// <summary>
/// Implementation of 1D Gaussian G(x) function
@ -56,7 +69,7 @@ namespace SixLabors.ImageSharp
float denominator = MathF.Sqrt(2 * MathF.PI) * sigma;
float exponentNumerator = -x * x;
float exponentDenominator = (float)(2 * Math.Pow(sigma, 2));
float exponentDenominator = 2 * Pow2(sigma);
float left = Numerator / denominator;
float right = MathF.Exp(exponentNumerator / exponentDenominator);
@ -98,14 +111,12 @@ namespace SixLabors.ImageSharp
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static float GetBcValue(float x, float b, float c)
{
float temp;
if (x < 0F)
{
x = -x;
}
temp = x * x;
float temp = x * x;
if (x < 1F)
{
x = ((12 - (9 * b) - (6 * c)) * (x * temp)) + ((-18 + (12 * b) + (6 * c)) * temp) + (6 - (2 * b));
@ -134,10 +145,7 @@ namespace SixLabors.ImageSharp
/// The bounding <see cref="Rectangle"/>.
/// </returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight)
{
return new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
}
public static Rectangle GetBoundingRectangle(Point topLeft, Point bottomRight) => new Rectangle(topLeft.X, topLeft.Y, bottomRight.X - topLeft.X, bottomRight.Y - topLeft.Y);
/// <summary>
/// Finds the bounding rectangle based on the first instance of any color component other

2
tests/ImageSharp.Benchmarks/ImageSharp.Benchmarks.csproj

@ -18,7 +18,7 @@
<PackageReference Include="Colourful" Version="1.2.1" />
<PackageReference Include="System.Numerics.Vectors" Version="4.4.0" />
<PackageReference Include="BenchmarkDotNet" Version="0.10.12" />
<PackageReference Include="Colourful" Version="1.1.2" />
<PackageReference Include="Colourful" Version="1.2.1" />
<PackageReference Include="System.Drawing.Common" Version="4.5.0-preview2-26202-05" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)'=='net461'">

3
tests/ImageSharp.Tests/Colorspaces/ColorSpaceEqualityTests.cs

@ -9,6 +9,7 @@ using SixLabors.ImageSharp.ColorSpaces;
using Xunit;
// ReSharper disable InconsistentNaming
// TODO: This needs to be refactored so that it uses a serializable type once the colorspace code is public
namespace SixLabors.ImageSharp.Tests.Colorspaces
{
/// <summary>
@ -33,7 +34,7 @@ namespace SixLabors.ImageSharp.Tests.Colorspaces
{nameof( YCbCr), YCbCr.Empty }
};
public static readonly IEnumerable<object[]> EmptyData = EmptyDataLookup.Select(x => new [] { x.Key });
public static readonly IEnumerable<object[]> EmptyData = EmptyDataLookup.Select(x => new[] { x.Key });
public static readonly TheoryData<object, object, Type> EqualityData =
new TheoryData<object, object, Type>

39
tests/ImageSharp.Tests/Helpers/ImageMathsTests.cs

@ -0,0 +1,39 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.ImageSharp.Tests.Helpers
{
using Xunit;
public class ImageMathsTests
{
[Fact]
public void FasAbsResultMatchesMath()
{
const int X = -33;
int expected = Math.Abs(X);
Assert.Equal(expected, ImageMaths.FastAbs(X));
}
[Fact]
public void Pow2ResultMatchesMath()
{
const float X = -33;
float expected = MathF.Pow(X, 2);
Assert.Equal(expected, ImageMaths.Pow2(X));
}
[Fact]
public void Pow3ResultMatchesMath()
{
const float X = -33;
float expected = MathF.Pow(X, 3);
Assert.Equal(expected, ImageMaths.Pow3(X));
}
}
}

2
tests/ImageSharp.Tests/TestUtilities/ApproximateFloatComparer.cs

@ -5,7 +5,7 @@ using System;
using System.Collections.Generic;
using System.Numerics;
using SixLabors.ImageSharp.ColorSpaces;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation.RgbColorSapce;
using SixLabors.ImageSharp.ColorSpaces.Conversion.Implementation;
namespace SixLabors.ImageSharp.Tests
{

Loading…
Cancel
Save