Skip to content

Commit

Permalink
Add optimized operations for spans
Browse files Browse the repository at this point in the history
  • Loading branch information
aalmada committed Dec 6, 2023
1 parent 0c67822 commit 46f810b
Show file tree
Hide file tree
Showing 56 changed files with 1,878 additions and 1,499 deletions.
6 changes: 6 additions & 0 deletions NetFabric.Numerics.sln
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Numerics.Geodesy"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFabric.Numerics.Geodesy.UnitTests", "src\NetFabric.Numerics.Geodesy.UnitTests\NetFabric.Numerics.Geodesy.UnitTests.csproj", "{4E4414C1-E5CF-4679-9016-7C3F70F13110}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NetFabric.Numerics.Tensors", "src\NetFabric.Numerics.Tensors\NetFabric.Numerics.Tensors.csproj", "{8D2EE0A5-32A2-4019-AD55-7E9B70B76D67}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -90,6 +92,10 @@ Global
{4E4414C1-E5CF-4679-9016-7C3F70F13110}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4E4414C1-E5CF-4679-9016-7C3F70F13110}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4E4414C1-E5CF-4679-9016-7C3F70F13110}.Release|Any CPU.Build.0 = Release|Any CPU
{8D2EE0A5-32A2-4019-AD55-7E9B70B76D67}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D2EE0A5-32A2-4019-AD55-7E9B70B76D67}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D2EE0A5-32A2-4019-AD55-7E9B70B76D67}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D2EE0A5-32A2-4019-AD55-7E9B70B76D67}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net7.0; net8.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
Expand Down
108 changes: 108 additions & 0 deletions src/NetFabric.Numerics.Angle.UnitTests/SpanAddTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
namespace NetFabric.Numerics.UnitTests;

public class SpanAddTests
{
public static TheoryData<Angle<Degrees, double>[], Angle<Degrees, double>, Angle<Degrees, double>[]> AddValueData
=> new()
{
{
Array.Empty<Angle<Degrees, double>>(),
new Angle<Degrees, double>(1),
Array.Empty<Angle<Degrees, double>>()
},
{
new Angle<Degrees, double>[] { new(1.0) },
new Angle<Degrees, double>(2.0),
new Angle<Degrees, double>[] { new(3.0) }
},
{
new Angle<Degrees, double>[] { new(1.0), new(11.0) },
new Angle<Degrees, double>(12.0),
new Angle<Degrees, double>[] { new(13.0), new(23.0) }
},
{
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value)).ToArray(),
new Angle<Degrees, double>(3.0),
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value + 3.0)).ToArray()
},
};

[Theory]
[MemberData(nameof(AddValueData))]
public void Add_Value_Should_Succeed(Angle<Degrees, double>[] source, Angle<Degrees, double> value, Angle<Degrees, double>[] expected)
{
// arrange
var result = new Angle<Degrees, double>[source.Length];

// act
Angle.Add(source, value, result);

// assert
result.Should().Equal(expected);
}

[Theory]
[MemberData(nameof(AddValueData))]
public void Add_Value_Inplace_Should_Succeed(Angle<Degrees, double>[] source, Angle<Degrees, double> value, Angle<Degrees, double>[] expected)
{
// arrange

// act
Angle.Add(source, value, source);

// assert
source.Should().Equal(expected);
}

public static TheoryData<Angle<Degrees, double>[], Angle<Degrees, double>[], Angle<Degrees, double>[]> AddData
=> new()
{
{
Array.Empty<Angle<Degrees, double>>(),
Array.Empty<Angle<Degrees, double>>(),
Array.Empty<Angle<Degrees, double>>()
},
{
new Angle<Degrees, double>[] { new(1.0) },
new Angle<Degrees, double>[] { new(3.0) },
new Angle<Degrees, double>[] { new(4.0) }
},
{
new Angle<Degrees, double>[] { new(1.0), new(11.0) },
new Angle<Degrees, double>[] { new(12.0), new(13.0) },
new Angle<Degrees, double>[] { new(13.0), new(24.0) }
},
{
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value)).ToArray(),
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value + 1.0)).ToArray(),
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value * 2.0 + 1.0)).ToArray()
},
};

[Theory]
[MemberData(nameof(AddData))]
public void Add_Should_Succeed(Angle<Degrees, double>[] left, Angle<Degrees, double>[] right, Angle<Degrees, double>[] expected)
{
// arrange
var result = new Angle<Degrees, double>[left.Length];

// act
Angle.Add<Degrees, double>(left, right, result);

// assert
result.Should().Equal(expected);
}

[Theory]
[MemberData(nameof(AddData))]
public void Add_Inplace_Should_Succeed(Angle<Degrees, double>[] left, Angle<Degrees, double>[] right, Angle<Degrees, double>[] expected)
{
// arrange

// act
Angle.Add<Degrees, double>(left, right, left);

// assert
left.Should().Equal(expected);
}
}
21 changes: 16 additions & 5 deletions src/NetFabric.Numerics.Angle.UnitTests/SumTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,22 @@ public class SumTests
public static TheoryData<Angle<Degrees, double>[], Angle<Degrees, double>> SumData
=> new()
{
{Array.Empty<Angle<Degrees, double>>(), new Angle<Degrees, double>(0)},
{new Angle<Degrees, double>[] { new(1.0) }, new Angle<Degrees, double>(1.0)},
{new Angle<Degrees, double>[] { new(1.0), new(11.0) }, new Angle<Degrees, double>(12.0)},
{new Angle<Degrees, double>[] { new(1.0), new(-11.0) }, new Angle<Degrees, double>(-10.0)},
{ Enumerable.Range(0, 1_000).Select(value => new Angle<Degrees, double>(1.0)).ToArray(), new Angle<Degrees, double>(1_000.0)},
{
Array.Empty<Angle<Degrees, double>>(),
new Angle<Degrees, double>(0)
},
{
new Angle<Degrees, double>[] { new(1.0) },
new Angle<Degrees, double>(1.0)
},
{
new Angle<Degrees, double>[] { new(1.0), new(11.0) },
new Angle<Degrees, double>(12.0)
},
{
Enumerable.Range(0, 97).Select(value => new Angle<Degrees, double>(value)).ToArray(),
new Angle<Degrees, double>(Enumerable.Range(0, 97).Sum())
},
};

[Theory]
Expand Down
4 changes: 0 additions & 4 deletions src/NetFabric.Numerics.Angle/Angle.cs
Original file line number Diff line number Diff line change
Expand Up @@ -221,11 +221,7 @@ public static int Sign<TUnits, T>(Angle<TUnits, T> angle)
public static Angle<TUnits, T> Lerp<TUnits, T>(Angle<TUnits, T> a1, Angle<TUnits, T> a2, T t)
where TUnits : IAngleUnits
where T : struct, IFloatingPointIeee754<T>, IMinMaxValue<T>
#if NET8_0_OR_GREATER
=> new(T.Lerp(a1.Value, a2.Value, t));
#else
=> new(Utils.Lerp(a1.Value, a2.Value, t));
#endif

/// <summary>
/// Returns the smallest of two angles.
Expand Down
37 changes: 37 additions & 0 deletions src/NetFabric.Numerics.Angle/AngleSpanOperations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using System.Runtime.InteropServices;

namespace NetFabric.Numerics;

public static partial class Angle
{
public static void Add<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> angles, Angle<TUnits, T> value, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Add(MemoryMarshal.Cast<Angle<TUnits, T>, T>(angles), value.Value, MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

public static void Add<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> left, ReadOnlySpan<Angle<TUnits, T>> right, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Add(MemoryMarshal.Cast<Angle<TUnits, T>, T>(left), MemoryMarshal.Cast<Angle<TUnits, T>, T>(right), MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

public static void Subtract<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> angles, Angle<TUnits, T> value, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Subtract(MemoryMarshal.Cast<Angle<TUnits, T>, T>(angles), value.Value, MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

public static void Subtract<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> left, ReadOnlySpan<Angle<TUnits, T>> right, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Subtract(MemoryMarshal.Cast<Angle<TUnits, T>, T>(left), MemoryMarshal.Cast<Angle<TUnits, T>, T>(right), MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

public static void Multiply<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> angles, Angle<TUnits, T> value, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Multiply(MemoryMarshal.Cast<Angle<TUnits, T>, T>(angles), value.Value, MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

public static void Divide<TUnits, T>(ReadOnlySpan<Angle<TUnits, T>> angles, Angle<TUnits, T> value, Span<Angle<TUnits, T>> result)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
=> Tensor.Divide(MemoryMarshal.Cast<Angle<TUnits, T>, T>(angles), value.Value, MemoryMarshal.Cast<Angle<TUnits, T>, T>(result));

}
21 changes: 1 addition & 20 deletions src/NetFabric.Numerics.Angle/AngleSum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,24 +64,5 @@ public static Angle<TUnits, T> Sum<TUnits, T>(this Span<Angle<TUnits, T>> source
public static Angle<TUnits, T> Sum<TUnits, T>(this ReadOnlySpan<Angle<TUnits, T>> source)
where TUnits : IAngleUnits
where T : struct, IFloatingPoint<T>, IMinMaxValue<T>
{
var sum = T.Zero;
if(Vector.IsHardwareAccelerated && source.Length > Vector<T>.Count * 2)
{
var vectors = MemoryMarshal.Cast<Angle<TUnits, T>, Vector<T>>(source);
var sumVector = Vector<T>.Zero;

foreach (ref readonly var vector in vectors)
sumVector += vector;

sum = sumVector.SumItems();
var remainder = source.Length % Vector<T>.Count;
source = source[^remainder..];
}
foreach (ref readonly var angle in source)
{
checked { sum += angle.Value; }
}
return new(sum);
}
=> new(Tensor.Sum(MemoryMarshal.Cast<Angle<TUnits, T>, T>(source)));
}
8 changes: 6 additions & 2 deletions src/NetFabric.Numerics.Angle/NetFabric.Numerics.Angle.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<Title>NetFabric.Numerics.Angle</Title>
<TargetFrameworks>net7.0; net8.0</TargetFrameworks>
<TargetFrameworks>net8.0</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Description>
A strongly-typed representation of an angle.
Expand Down Expand Up @@ -39,15 +39,19 @@
</ItemGroup>

<ItemGroup>
<PackageReference Include="NetFabric" Version="1.5.0" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="NetFabric" Version="1.4.1" />
<PackageReference Include="NetFabric.Hyperlinq.Analyzer" Version="2.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NetFabric.Numerics.Tensors\NetFabric.Numerics.Tensors.csproj" />
</ItemGroup>

</Project>
13 changes: 0 additions & 13 deletions src/NetFabric.Numerics.Angle/Utils.cs

This file was deleted.

14 changes: 0 additions & 14 deletions src/NetFabric.Numerics.Angle/VectorExtensions.cs

This file was deleted.

69 changes: 0 additions & 69 deletions src/NetFabric.Numerics.Benchmarks/AdditionVectorDoubleBenchmark.cs

This file was deleted.

Loading

0 comments on commit 46f810b

Please sign in to comment.