diff --git a/Directory.Build.props b/Directory.Build.props
index f9399d5..65ab0a1 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -38,23 +38,21 @@
John Kelly and Contributors
$(BaseArtifactsPath)bin/$(BaseArtifactsPathSuffix)/
- johnkellyoxford
+ John Kelly
$(BaseArtifactsPath)pkg/$(BaseArtifactsPathSuffix)/$(Configuration)/
MathSharp
- 0.0.1
- alpha
+ 2.0.0
+ pre
- $(MSBuildThisFileDirectory)MathSharp.snk
- Copyright � John Kelly and Contributors
- A high speed vector maths library
+ Copyright (C) John Kelly and Contributors
+ MathSharp is a vector and matrix library written in C# using hardware intrinsics. Thanks to hardware acceleration, MathSharp is significantly faster than most mathematics libraries out there.
strict
false
true
preview
- 00240000048000009400000006020000002400005253413100040000010001000586cd22205c2991de00dea27c3455744874d5b9c4532ccee2bf8fa9b55752af42fa6170f641c20d1501cd3b9e6d22a1327cdaf19eb8eba23e8ed350a60930e7286417916e3a3a39798e69d8d521ac3af4c720cbcca2f2fbf5cee2c0b1c6be08ebba9051399148c663c3408513be9a2ff96e7816bb1b3713d1f30e13fa2e66a9
en-GB
true
MIT
@@ -74,4 +72,4 @@
-
\ No newline at end of file
+
diff --git a/README.md b/README.md
index d4960a5..18e8830 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,13 @@
# MathSharp
+# Note: As of 2022 MathSharp is not recommended for general use
+# Since its inception, the .NET intrinsics and vectors have increased in performance and functionality massively, and they are recommended for any new projects
+
[](https://ko-fi.com/johnhk)
[](https://www.buymeacoffee.com/johnhk)
[](https://github.com/john-h-k/MathSharp/blob/master/LICENSE)
[](https://GitHub.com/john-h-k/MathSharp/issues/)
-[](https://GitHub.com/john-h-k/MathSharp/stargazers/)
-
|Configuration|Windows x86|Windows x64|Ubuntu 1604 x64|Mac OS x64|
@@ -122,7 +123,8 @@ Vector4 + Vector4;
### Results (within margin of error between MathSharp and System.Numerics)
-
+
+
| Method | Mean | Error | StdDev |
|--------------- |----------:|----------:|----------:|
diff --git a/docs/Comparisons-And-Selections.md b/docs/Comparisons-And-Selections.md
new file mode 100644
index 0000000..8c32ac5
--- /dev/null
+++ b/docs/Comparisons-And-Selections.md
@@ -0,0 +1,97 @@
+# Comparisons
+
+MathSharp offers all the comparisons you'd expect - but they don't necessarily work in the way you'd expect from working with other libraries.
+Most comparison results return the same type you give them, rather than `bool` or multiple `bool`s. You might find this confusing, but it'll make sense soon.
+
+Let's start with the simple comparisons. You want to check if all or any elements of a vector are true or false for a comparison. This is really easily achieved with extension methods.
+For example - test if 2 vectors are equal:
+
+```cs
+public bool AreEqual(Vector128 left, Vector128 right)
+{
+ var comp = Vector.CompareEqual(left, right);
+ return comp.AllTrue(); // returns true if all elements in the comparison are true, else false
+}
+```
+
+Tada! It's that simple. The 4 simplest comparison extensions are:
+
+```cs
+AllTrue() - true if all elements of the comparison are true
+AllFalse() - true if all elements of the comparison are false
+AllFalse() - true if any elements of the comparison are true
+AnyFalse() - true if any elements of the comparison are false
+```
+
+First, a quick brush up on bitwise operations. A bitwise `and`/`&`, results in a bit being set if both inputs are set. Else it is zero.
+A bitwise `or`/`|`, results in a bit being set if either or both inputs are set. If both are zero, it is zero. E.g
+
+```cs
+// 0b indicates a binary literal. & is and, | is or
+0b_1 & 0b_1 -> 1
+0b_0 & 0b_1 -> 0
+0b_1 & 0b_0 -> 0
+0b_0 & 0b_0 -> 0
+
+0b_1 | 0b_1 -> 1
+0b_0 | 0b_1 -> 1
+0b_1 | 0b_0 -> 1
+0b_0 | 0b_0 -> 0
+```
+
+Also remember that all values on your computer are binary. Floating point types are complex, but they're still a chunk of binary data and nothing more.
+So, let's give an example operation we want to do. Say we have a vector, and we want to multiply all numbers on it by another vector, if they are equal to the numbers in the other vector, else, we want to square root them.
+E,g `<99, -5, 6, -2.3>, <99, 7, 0.1, -2.3>` would become `<99 * 99, Sqrt(-5), Sqrt(6), -2.3 * -2.3>`. Let's write this using `System.Numerics`
+
+```cs
+public Vector4 Foo(Vector4 left, Vector4 right)
+{
+ var mul = left * right;
+ var sqrt = Vector4.SquareRoot(mul);
+
+ // No way to vectorise this :()
+ var x = left.X == right.X ? left.X * right.X : MathF.Sqrt(left.X);
+ var y = left.Y == right.Y ? left.Y * right.Y : MathF.Sqrt(left.Y);
+ var z = left.Z == right.Z ? left.Z * right.Z : MathF.Sqrt(left.Z);
+ var w = left.W == right.W ? left.W * right.W : MathF.Sqrt(left.W);
+ return new Vector4(x, y, z, w);
+}
+```
+
+On my system, this takes about 3 nanoseconds. Not bad eh!
+
+Now let's look at MathSharp implementation:
+
+```cs
+public Vector128 Foo(Vector128 left, Vector128 right)
+{
+ var comp = Vector.CompareEqual(left, right);
+ var mul = Vector.Multiply(left, right);
+ var sqrt = Vector.Sqrt(mul);
+
+ return Vector.Select(sqrt, mul, comp);
+}
+```
+
+Again on my system, this takes 0.3 nanoseconds. That's a 10x speedup!
+So, what does it do?
+
+First, it does the comparison. `Vector.CompareEqual` returns a `Vector128`, as mentioned above. However, what's important is what is in that return.
+Each element is either all-1s or all-0s as binary. This means, that you can use them as masks. For example, to select all elements of a vector that are equal to another, and zero the rest, you just do
+
+```cs
+Vector.And(left, Vector.CompareEqual(left, right));
+```
+
+E.g, with `<1, 2, 3, 4>` and `<1, 3, 3, 5>`, the comparison returns `<0xFFFFFFFF, 0, 0xFFFFFFFF, 0>`. When we perform the `and`, as we learnt above, the elements with 0 are discarded, and the ones with `0xFFFFFFFF` (which is all bits set) are kept.
+
+Given the commonness of this operation, MathSharp provides 3 selection helper methods:
+
+```cs
+SelectWhereTrue(selector, vector)
+SelectWhereFalse(selector, vector)
+Select(selector, left, right)
+```
+
+`SelectWhereTrue` and `SelectWhereFalse` are reasonably self explanatory. They select elements from `vector` which correspond to `true` elements of the `selector` (usually created with a `Vector.Compare...` method).
+`Select` works like a ternary expression, selecting elements from `left` where `selector` is true, and from `right` where `selector` is `false`. In the above example, we select the multiplied value when the values are equal, else we select the square root value.
\ No newline at end of file
diff --git a/docs/Introduction.md b/docs/Introduction.md
new file mode 100644
index 0000000..7b92e2e
--- /dev/null
+++ b/docs/Introduction.md
@@ -0,0 +1,66 @@
+# What is MathSharp
+
+MathSharp is a library designed around blazing-fast, platform-agnostic linear algebra and 3D maths.
+
+## What are the advantages of MathSharp over its competitors?
+
+MathSharp is faster! Check our [benchmarks](https://github.com/john-h-k/MathSharp/blob/master/README.md). We offer a more complete feature set than `System.Numerics`, with faster inclusion of new features (such as colour and collision support, which are currently in the works). We also offer fully-fledged double-precision vector, quaternion, and matrix types in .NET Core 3.0, which `System.Numerics` doesn't.
+
+## That sounds great, but what does using MathSharp look like?
+
+Let's take a relatively simple example. You have some code, using the `System.Numeric`s types, that just finds the cross product of 2 pairs of vectors, then finds the dot of that.
+
+```cs
+public void DotAndCross(Vector3 left0, Vector3 left1, Vector3 right0, Vector3 right1, out Vector3 result)
+{
+ var leftDot = new Vector3(Vector3.Dot(left0, left1));
+ var rightDot = new Vector3(Vector3.Dot(right0, right1));
+ result = Vector3.Cross(leftDot, rightDot);
+}
+```
+
+So, the first step is take the incoming `Vector3` params by reference. This isn't always necessary, but it allows you to take advantage of better loading on some platforms.
+
+Then, we convert the `System.Numerics` types to the native SIMD types by using MathSharp's extension methods. `Load()` takes a `Vector3`, and returns a `Vector128`.
+We then use the static methods in `MathSharp.Vector` to perform our operations. Here, we want to perform a 3D dot and cross.
+
+We then finally use the `Vector.Store` method to store out SIMD type into our storage type.
+
+```cs
+using MathSharp; // Include at the top
+
+public void DotAndCross(in Vector3 left0, in Vector3 left1, in Vector3 right0, in Vector3 right1, out Vector3 result)
+{
+ var leftDot = Vector.Dot3D(left0.Load(), left1.Load());
+ var rightDot = Vector.Dot3D(right0.Load(), right1.Load());
+
+ Vector.Store(Vector.Cross3D(leftDot, rightDot), out result);
+}
+```
+
+Tada! You've just used MathSharp without even making a breaking change. This is still a great way to use it - but not the best.
+
+The idiomatic, fastest way to use MathSharp, is to pass around the SIMD types as arguments and returns, and use the so-called storage types - such as `System.Numerics` and `OpenTk.Maths` types, as well as your custom storage types, for fields and members of other types. For more information about this as well as creating your own storage types, check out [storage](storage.md). For example, rewriting the above method to be idiomatic MathSharp would be
+
+```cs
+using MathSharp; // Include at the top
+
+public Vector128 DotAndCross(Vector128 left0, Vector128 left1, Vector128 right0, Vector128 right1)
+{
+ var leftDot = Vector.Dot3D(left0, left1);
+ var rightDot = Vector.Dot3D(right0, right1);
+
+ return Vector.Cross3D(leftDot, rightDot);
+}
+```
+
+The key MathSharp types are:
+
+* `Vector` - a static class containing methods to work with vectors
+* `Matrix` - a static class containing methods to work with matrixes
+* `Quaternion` - a static class containing methods to work with quaternions
+* `MatrixSingle` - a struct used to represent a single-precision 4x4 matrix SIMD type
+
+Comparisons in MathSharp are extremely powerful - allowing you to perform a far wide variety
+of comparison and selection operations, and to use those comparisons in ways that other libraries simply don't. If you've ever worked with SIMD before, these comparisons will be intuitive to you. If not, they're still easy to learn, and unlock a wide range of operations. Check out our [comparisons](comparisons-and-selections.md) doc for more.
+
diff --git a/docs/Storage.md b/docs/Storage.md
new file mode 100644
index 0000000..10bf00e
--- /dev/null
+++ b/docs/Storage.md
@@ -0,0 +1,27 @@
+# Storage
+
+MathSharp operations are designed to occur with locals and arguments, which are located on the stack or SIMD registers, allowing them to be fast and efficient. Because of this,
+the types worked with are generally larger than you would expect or have specific alignment requirements, and don't distinguish between different dimensions. Generally, you should use other types
+for fields and members of types, and then use SIMD types for passing parameters or returns. This will result in the best performance and the minimum number of conversions between storage and SIMD types.
+
+By default, MathSharp supports using the `System.Numerics` types as storage types, and provides `Load()` extension methods in `Vector, Matrix, Quaternion`, and `Store(out T store)` methods too.
+Writing your own storage types is trivial. Use the `FromVector` and `ToVector` methods to convert the types. As an example, here is a custom Vector3 storage type.
+
+```cs
+public struct MyVec3
+{
+ public float X, Y, Z;
+
+ public Vector128 Load() => Vector.FromVector3D(in x);
+}
+
+public static class MyVec3Extensions
+{
+ public static void Store(this Vector128 vector, out MyVec3 vec3) => Vector.ToVector3D(vector, vec3);
+}
+```
+
+You can use the aligned variants of these methods (e.g `FromVector3DAligned`) if you can guarantee the passed value is always 16 byte aligned for `float`s, and 32 byte aligned for `double`s.
+
+Passing by `in` is very important, because it ensures you are actually passing a reference. We don't take `ref` because we want to allow readonly members to be passed.
+The load and from methods also have pointer overloads. Where these can be called without pinning, they should be used for potential performance benefits.
\ No newline at end of file
diff --git a/samples/MathSharp.Interactive/Benchmarks/Vector/Single/CameraClassBenchmark.cs b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/CameraClassBenchmark.cs
index 85c7b9c..fcb76e4 100644
--- a/samples/MathSharp.Interactive/Benchmarks/Vector/Single/CameraClassBenchmark.cs
+++ b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/CameraClassBenchmark.cs
@@ -5,7 +5,7 @@
namespace MathSharp.Interactive.Benchmarks.Vector.Single
{
using Vector = MathSharp.Vector;
- using Vector3 = OpenTK.Vector3;
+ using Vector3 = System.Numerics.Vector3;
public class CameraClassBenchmark
{
@@ -21,7 +21,7 @@ public class CameraClassBenchmark
[GlobalSetup]
public void Setup()
{
- _pitch = 11f;
+ _pitch = 11f;
_yaw = 0.008888f;
_unitY = Vector128.Create(0f, 1f, 0f, 0f);
_unitYWrapper = _unitY;
@@ -38,12 +38,27 @@ public Vector128 MathSharp()
{
Vector128 front = _mathSharpFront;
front = Vector.Normalize3D(front);
- Vector128 right = Vector.Normalize3D(Vector.CrossProduct3D(_unitY, front));
+ Vector128 right = Vector.Normalize3D(Vector.Cross3D(_unitY, front));
- Vector128 up = Vector.Normalize3D(Vector.CrossProduct3D(front, right));
+ Vector128 up = Vector.Normalize3D(Vector.Cross3D(front, right));
return up;
}
+ public void DotAndCross(Vector3 left0, Vector3 left1, Vector3 right0, Vector3 right1, out Vector3 result)
+ {
+ var leftDot = new Vector3(Vector3.Dot(left0, left1));
+ var rightDot = new Vector3(Vector3.Dot(right0, right1));
+ result = Vector3.Cross(leftDot, rightDot);
+ }
+
+ public void DotAndCross(in Vector3 left0, in Vector3 left1, in Vector3 right0, in Vector3 right1, out Vector3 result)
+ {
+ var leftDot = Vector.Dot3D(left0.Load(), left1.Load());
+ var rightDot = Vector.Dot3D(right0.Load(), right1.Load());
+
+ Vector.Store(Vector.Cross3D(leftDot, rightDot), out result);
+ }
+
[Benchmark]
public Vector3 OpenTkMath()
{
diff --git a/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SelectionBenchmark.cs b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SelectionBenchmark.cs
new file mode 100644
index 0000000..29ab602
--- /dev/null
+++ b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SelectionBenchmark.cs
@@ -0,0 +1,62 @@
+using BenchmarkDotNet.Attributes;
+using System;
+using System.Collections.Generic;
+using System.Numerics;
+using System.Runtime.CompilerServices;
+using System.Runtime.Intrinsics;
+using System.Runtime.Intrinsics.X86;
+using System.Text;
+
+using MVector = MathSharp.Vector;
+
+namespace MathSharp.Interactive.Benchmarks.Vector.Single
+{
+ public class SelectionBenchmark
+ {
+ private Vector4 _value = new Vector4(99, -5, 6, -2.3f);
+ private Vector4 _multiply = new Vector4(99, 7, 0.1f, -2.3f);
+
+
+ private Vector128 _value1 = Vector128.Create(99, -5, 6, -2.3f);
+ private Vector128 _multiply1 = Vector128.Create(99, 7, 0.1f, -2.3f);
+
+ [Benchmark]
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public Vector4 SysNumeric() => Foo(_value, _multiply);
+
+ [Benchmark]
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public Vector128 MathSharp() => Foo(_value1, _multiply1);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public Vector4 Foo(Vector4 left, Vector4 right)
+ {
+ var mul = left * right;
+ var sqrt = Vector4.SquareRoot(mul);
+ // No way to vectorise this :(
+ var x = left.X == right.X ? left.X * right.X : sqrt.X;
+ var y = left.Y == right.Y ? left.Y * right.Y : sqrt.Y;
+ var z = left.Z == right.Z ? left.Z * right.Z : sqrt.Z;
+ var w = left.W == right.W ? left.W * right.W : sqrt.W;
+ return new Vector4(x, y, z, w);
+ }
+
+ //[MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)]
+ //public static Vector128 MulNegAndAbs_MathSharp(Vector128 value, Vector128 multiply)
+ //{
+ // var mul = Sse.Multiply(Sse.Xor(value, Vector128.Create(int.MinValue).AsSingle()), multiply);
+ // mul = Sse.Max(mul, value);
+ // return Sse.And(mul, Vector128.Create(~int.MinValue).AsSingle());
+ //}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
+ public Vector128 Foo(Vector128 left, Vector128 right)
+ {
+ var comp = MVector.CompareEqual(left, right);
+ var mul = MVector.Multiply(left, right);
+ var sqrt = MVector.Sqrt(mul);
+
+ return MVector.Select(comp, mul, sqrt);
+ }
+ }
+}
diff --git a/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SineWaveBenchmark.cs b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SineWaveBenchmark.cs
index 3d4bcb3..84755b9 100644
--- a/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SineWaveBenchmark.cs
+++ b/samples/MathSharp.Interactive/Benchmarks/Vector/Single/SineWaveBenchmark.cs
@@ -1,4 +1,5 @@
using BenchmarkDotNet.Attributes;
+using OpenTK;
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
diff --git a/samples/MathSharp.Interactive/MathSharp.Interactive.csproj b/samples/MathSharp.Interactive/MathSharp.Interactive.csproj
index 9545180..c520811 100644
--- a/samples/MathSharp.Interactive/MathSharp.Interactive.csproj
+++ b/samples/MathSharp.Interactive/MathSharp.Interactive.csproj
@@ -3,8 +3,8 @@
1573;1591;NU1701;CS0649;CS1591;
Exe
- netcoreapp3.0
- preview
+ netcoreapp3.1
+ 8.0
false
@@ -17,7 +17,7 @@
-
+
diff --git a/samples/MathSharp.Interactive/Program.cs b/samples/MathSharp.Interactive/Program.cs
index e5934bb..620a547 100644
--- a/samples/MathSharp.Interactive/Program.cs
+++ b/samples/MathSharp.Interactive/Program.cs
@@ -7,6 +7,11 @@
using System.Runtime.Intrinsics.X86;
using MathSharp.StorageTypes;
using MathSharp;
+
+using MathSharp.Interactive.Benchmarks.Vector.Single;
+
+using Vector4 = System.Numerics.Vector4;
+=======
using BenchmarkDotNet.Attributes;
using System.Reflection;
using BenchmarkDotNet.Running;
@@ -17,29 +22,7 @@ internal unsafe class Program
{
public static void Main(string[] args)
{
- var rand = new Random();
- var inside = 0;
-
- const int sampleSize = 1_000_000_000;
-
- for (var i = 0; i < sampleSize; i++)
- {
- if (IsInCircle(0.25, rand.NextDouble() - 0.5, rand.NextDouble() - 0.5)) inside++;
- }
-
- Avx2.LoadV
-
- Console.WriteLine(4 * (double)inside / sampleSize);
-
- static bool IsInCircle(double radiusSquared, double x, double y)
- {
- return x * x + y * y < radiusSquared;
- }
- }
-
- public static Vector128 IsInCircle(Vector128 radius, Vector128 x, Vector128 y)
- {
- return Vector.CompareLessThanOrEqual(Vector.Sqrt(Vector.Add(Vector.Square(x), Vector.Square(y))), radius);
+ BenchmarkRunner.Run();
}
}
}
\ No newline at end of file
diff --git a/sources/Directory.Build.props b/sources/Directory.Build.props
index 89031a5..98f11cb 100644
--- a/sources/Directory.Build.props
+++ b/sources/Directory.Build.props
@@ -13,6 +13,7 @@
$(MSBuildAllProjects);$(MSBuildThisFileDirectory)..\Directory.Build.props
sources
+ true
diff --git a/sources/MathSharp/MathSharp.csproj b/sources/MathSharp/MathSharp.csproj
index f999573..db11e10 100644
--- a/sources/MathSharp/MathSharp.csproj
+++ b/sources/MathSharp/MathSharp.csproj
@@ -1,15 +1,10 @@
-
- netcoreapp3.0
+
+ netcoreapp3.1
false
-
-
-
-
-
diff --git a/sources/MathSharp/Matrix/MatrixSingle/BasicMaths.cs b/sources/MathSharp/Matrix/MatrixSingle/BasicMaths.cs
index 61889b1..ab75366 100644
--- a/sources/MathSharp/Matrix/MatrixSingle/BasicMaths.cs
+++ b/sources/MathSharp/Matrix/MatrixSingle/BasicMaths.cs
@@ -9,6 +9,12 @@ public static partial class Matrix
private const MethodImplOptions MaxOpt =
MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization;
+ ///
+ /// Performs an element-wise matrix addition on the 2 s
+ ///
+ /// The left matrix to add
+ /// The right matrix to add
+ /// A with its components added
[MethodImpl(MaxOpt)]
public static MatrixSingle Add(in MatrixSingle left, in MatrixSingle right) =>
new MatrixSingle(
@@ -18,6 +24,12 @@ public static MatrixSingle Add(in MatrixSingle left, in MatrixSingle right) =>
Vector.Add(left._v3, right._v3)
);
+ ///
+ /// Performs an element-wise matrix addition on the 2 s
+ ///
+ /// The left matrix to add
+ /// The right matrix to add
+ /// A with its components added
[MethodImpl(MaxOpt)]
public static unsafe MatrixSingle Add(MatrixSingle* left, MatrixSingle* right) =>
new MatrixSingle(
@@ -27,7 +39,12 @@ public static unsafe MatrixSingle Add(MatrixSingle* left, MatrixSingle* right) =
Vector.Add(left->_v3, right->_v3)
);
-
+ ///
+ /// Performs an element-wise matrix subtraction on the 2 s
+ ///
+ /// The left matrix to subtract
+ /// The right matrix to subtract
+ /// A with its components subtracted
[MethodImpl(MaxOpt)]
public static MatrixSingle Subtract(in MatrixSingle left, in MatrixSingle right) =>
new MatrixSingle(
@@ -38,6 +55,11 @@ public static MatrixSingle Subtract(in MatrixSingle left, in MatrixSingle right)
);
+ ///
+ /// Performs an element-wise negation on a s
+ ///
+ /// The matrix to negate
+ /// A with its components negated
[MethodImpl(MaxOpt)]
public static MatrixSingle Negate(in MatrixSingle matrix) =>
new MatrixSingle(
@@ -47,6 +69,12 @@ public static MatrixSingle Negate(in MatrixSingle matrix) =>
Vector.Negate(matrix._v3)
);
+ ///
+ /// Performs an element-wise matrix multiplication on the 2 s
+ ///
+ /// The left matrix to multiply
+ /// The right matrix to multiply
+ /// A with its components multiplied
[MethodImpl(MaxOpt)]
public static MatrixSingle ScalarMultiply(in MatrixSingle left, Vector128 vectorOfScalar) =>
new MatrixSingle(
@@ -57,11 +85,21 @@ public static MatrixSingle ScalarMultiply(in MatrixSingle left, Vector128
);
+ ///
+ /// Performs an element-wise matrix multiplication on a and a
+ ///
+ /// The left matrix to multiply
+ /// The scalar to multiply it by
+ /// A new with its components added
[MethodImpl(MaxOpt)]
public static MatrixSingle ScalarMultiply(in MatrixSingle left, float scalar)
=> ScalarMultiply(left, Vector128.Create(scalar));
-
+ ///
+ /// Transposes a
+ ///
+ /// The matrix to transpose
+ /// A new , transposed
[MethodImpl(MaxOpt)]
public static MatrixSingle Transpose(in MatrixSingle matrix)
{
diff --git a/sources/MathSharp/Matrix/MatrixSingle/MatrixOperations.cs b/sources/MathSharp/Matrix/MatrixSingle/MatrixOperations.cs
index 107d704..ad77fff 100644
--- a/sources/MathSharp/Matrix/MatrixSingle/MatrixOperations.cs
+++ b/sources/MathSharp/Matrix/MatrixSingle/MatrixOperations.cs
@@ -134,9 +134,9 @@ public static MatrixSingle CreateBillboard(Vector128 objectPosition, Vect
? Vector.Negate(cameraForwardVector)
: Multiply(z, Divide(SingleConstants.AllBitsSet, Sqrt(norm)));
- Vector128 x = Normalize3D(CrossProduct3D(cameraUpVector, z));
+ Vector128 x = Normalize3D(Cross3D(cameraUpVector, z));
- Vector128 y = CrossProduct3D(z, x);
+ Vector128 y = Cross3D(z, x);
// We need W to be zero for x, y, and z, and 1.0f for objectPosition. They are currently undefined
x = And(x, SingleConstants.MaskW);
@@ -271,14 +271,14 @@ public static unsafe bool Decompose(MatrixSingle matrix, out Vector128 sc
Rank3Decompose(out _, out _, out int cc, absX, absY, absZ);
- *pVectorBasis[b] = CrossProduct3D(*pVectorBasis[a], *pCanonicalBasis[cc]);
+ *pVectorBasis[b] = Cross3D(*pVectorBasis[a], *pCanonicalBasis[cc]);
}
*pVectorBasis[b] = Normalize3D(*pVectorBasis[b]);
if (Unsafe.Add(ref pFloat0, c) < DecomposeEpsilon)
{
- *pVectorBasis[c] = CrossProduct3D(*pVectorBasis[a], *pVectorBasis[b]);
+ *pVectorBasis[c] = Cross3D(*pVectorBasis[a], *pVectorBasis[b]);
}
*pVectorBasis[c] = Normalize3D(*pVectorBasis[c]);
@@ -345,7 +345,7 @@ public static Vector128 Determinant(MatrixSingle matrix)
r = FastNegateMultiplyAdd(v1, p1, r);
r = FastMultiplyAdd(v2, p2, r);
- return DotProduct4D(s, r);
+ return Dot4D(s, r);
}
[MethodImpl(MaxOpt)]
diff --git a/sources/MathSharp/Quaternion/Quaternion.cs b/sources/MathSharp/Quaternion/Quaternion.cs
index f049a79..d78026c 100644
--- a/sources/MathSharp/Quaternion/Quaternion.cs
+++ b/sources/MathSharp/Quaternion/Quaternion.cs
@@ -30,7 +30,7 @@ public static Vector128 Inverse(Vector128 quaternion)
}
public static Vector128 DotProduct(Vector128 left, Vector128 right)
- => Vector.DotProduct4D(left, right);
+ => Vector.Dot4D(left, right);
public static Vector128 Add(Vector128 left, Vector128 right)
=> Vector.Add(left, right);
@@ -69,7 +69,7 @@ public static Vector128 Slerp(Vector128 left, Vector128 rig
var cosOmega = DotProduct(left, right);
var control = Vector.CompareLessThan(cosOmega, Vector128.Zero);
- var sign = Vector.Select(Vector.SingleConstants.One, Vector.SingleConstants.NegativeOne, control);
+ var sign = Vector.Select(control, Vector.SingleConstants.NegativeOne, Vector.SingleConstants.One);
cosOmega = Vector.Multiply(cosOmega, sign);
@@ -90,7 +90,7 @@ public static Vector128 Slerp(Vector128 left, Vector128 rig
s0 = Vector.Sin(s0);
s0 = Vector.Divide(s0, sinOmega);
- s0 = Vector.Select(v01, s0, control);
+ s0 = Vector.Select(control, s0, v01);
var s1 = Vector.FillWithY(s0);
s0 = Vector.FillWithX(s0);
diff --git a/sources/MathSharp/Vector/Shared/BitComparisons.cs b/sources/MathSharp/Vector/Shared/BitComparisons.cs
index 2a42c0e..fd851e1 100644
--- a/sources/MathSharp/Vector/Shared/BitComparisons.cs
+++ b/sources/MathSharp/Vector/Shared/BitComparisons.cs
@@ -8,11 +8,11 @@ namespace MathSharp
public static partial class Vector
{
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit8Equal(Vector128 left, Vector128 right)
- => CompareBit8Equal(left.AsSByte(), right.AsSByte()).AsByte();
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
+ => CompareEqual(left.AsSByte(), right.AsSByte()).AsByte();
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit8Equal(Vector128 left, Vector128 right)
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
{
if (Sse2.IsSupported)
{
@@ -35,11 +35,11 @@ static Vector128 SoftwareFallback(Vector128 left, Vector128
}
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit8Equal(Vector256 left, Vector256 right)
- => CompareBit8Equal(left.AsSByte(), right.AsSByte()).AsByte();
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
+ => CompareEqual(left.AsSByte(), right.AsSByte()).AsByte();
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit8Equal(Vector256 left, Vector256 right)
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
{
if (Avx2.IsSupported)
{
@@ -62,11 +62,11 @@ static Vector256 SoftwareFallback(Vector256 left, Vector256
}
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit16Equal(Vector128 left, Vector128 right)
- => CompareBit16Equal(left.AsInt16(), right.AsInt16()).AsUInt16();
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
+ => CompareEqual(left.AsInt16(), right.AsInt16()).AsUInt16();
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit16Equal(Vector128 left, Vector128 right)
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
{
if (Sse2.IsSupported)
{
@@ -89,11 +89,11 @@ static Vector128 SoftwareFallback(Vector128 left, Vector128
}
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit16Equal(Vector256 left, Vector256 right)
- => CompareBit16Equal(left.AsInt16(), right.AsInt16()).AsUInt16();
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
+ => CompareEqual(left.AsInt16(), right.AsInt16()).AsUInt16();
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit16Equal(Vector256 left, Vector256 right)
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
{
if (Avx2.IsSupported)
{
@@ -116,11 +116,11 @@ static Vector256 SoftwareFallback(Vector256 left, Vector256
}
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit32Equal(Vector128 left, Vector128 right)
- => CompareBit32Equal(left.AsInt32(), right.AsInt32()).AsUInt32();
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
+ => CompareEqual(left.AsInt32(), right.AsInt32()).AsUInt32();
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit32Equal(Vector128 left, Vector128 right)
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
{
if (Sse2.IsSupported)
{
@@ -143,11 +143,11 @@ static Vector128 SoftwareFallback(Vector128 left, Vector128 right
}
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit32Equal(Vector256 left, Vector256 right)
- => CompareBit32Equal(left.AsInt32(), right.AsInt32()).AsUInt32();
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
+ => CompareEqual(left.AsInt32(), right.AsInt32()).AsUInt32();
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit32Equal(Vector256 left, Vector256 right)
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
{
if (Avx2.IsSupported)
{
@@ -170,11 +170,11 @@ static Vector256 SoftwareFallback(Vector256 left, Vector256 right
}
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit64Equal(Vector128 left, Vector128 right)
- => CompareBit64Equal(left.AsInt64(), right.AsInt64()).AsUInt64();
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
+ => CompareEqual(left.AsInt64(), right.AsInt64()).AsUInt64();
[MethodImpl(MaxOpt)]
- public static Vector128 CompareBit64Equal(Vector128 left, Vector128 right)
+ public static Vector128 CompareEqual(Vector128 left, Vector128 right)
{
if (Sse41.IsSupported)
{
@@ -197,11 +197,11 @@ static Vector128 SoftwareFallback(Vector128 left, Vector128 ri
}
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit64Equal(Vector256 left, Vector256 right)
- => CompareBit64Equal(left.AsInt64(), right.AsInt64()).AsUInt64();
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
+ => CompareEqual(left.AsInt64(), right.AsInt64()).AsUInt64();
[MethodImpl(MaxOpt)]
- public static Vector256 CompareBit64Equal(Vector256 left, Vector256 right)
+ public static Vector256 CompareEqual(Vector256 left, Vector256 right)
{
if (Avx2.IsSupported)
{
diff --git a/sources/MathSharp/Vector/Shared/BitOperations.T.cs b/sources/MathSharp/Vector/Shared/BitOperations.T.cs
index ac60e90..ed8fef9 100644
--- a/sources/MathSharp/Vector/Shared/BitOperations.T.cs
+++ b/sources/MathSharp/Vector/Shared/BitOperations.T.cs
@@ -13,29 +13,30 @@ public static partial class Vector
///
/// The type of each element in and
/// The type of each element in
- /// The vector where elements are chosen from if the equivalent element in is false
- /// The vector where elements are chosen from if the equivalent element in is true
/// The selector used to select elements from and
+ /// The vector where elements are chosen from if the equivalent element in is
+ /// The vector where elements are chosen from if the equivalent element in is
/// A new with the elements selected by
[MethodImpl(MaxOpt)]
- public static Vector128 Select(Vector128 left, Vector128 right, Vector128 selector)
+ public static Vector128 Select(Vector128 selector, Vector128 left, Vector128 right)
where T : struct where U : struct
{
if (Sse41.IsSupported)
{
+ // BlendVariable takes what to insert if false, then if true
if (typeof(T) == typeof(float))
{
- return Sse41.BlendVariable(left.AsSingle(), right.AsSingle(), selector.AsSingle()).As();
+ return Sse41.BlendVariable(right.AsSingle(), left.AsSingle(), selector.AsSingle()).As();
}
else if (typeof(T) == typeof(double))
{
- return Sse41.BlendVariable(left.AsDouble(), right.AsDouble(), selector.AsDouble()).As();
+ return Sse41.BlendVariable(right.AsDouble(), left.AsDouble(), selector.AsDouble()).As();
}
- return Sse41.BlendVariable(left.AsByte(), right.AsByte(), selector.AsByte()).As();
+ return Sse41.BlendVariable(right.AsByte(), left.AsByte(), selector.AsByte()).As();
}
- return Or(And(selector.As(), right), AndNot(selector.As(), left));
+ return Or(And(selector.As(), left), AndNot(selector.As(), right));
}
///
@@ -44,11 +45,11 @@ public static Vector128 Select(Vector128 left, Vector128 right, V
///
/// The type of each element in
/// The type of each element in
- /// The vector to select elements from
/// The vector to use to select elements from
+ /// The vector to select elements from
/// A new with the elements selected by retained and the others zeroed
[MethodImpl(MaxOpt)]
- public static Vector128 SelectWhereTrue(Vector128 vector, Vector128 selector)
+ public static Vector128 SelectWhereTrue(Vector128 selector, Vector128 vector)
where T : struct where U : struct
=> And(selector.As(), vector);
@@ -58,11 +59,11 @@ public static Vector128 SelectWhereTrue(Vector128 vector, Vector128<
///
/// The type of each element in
/// The type of each element in
- /// The vector to select elements from
/// The vector to use to select elements from
+ /// The vector to select elements from
/// A new with the elements selected by retained and the others zeroed
[MethodImpl(MaxOpt)]
- public static Vector128 SelectWhereFalse(Vector128 vector, Vector128 selector)
+ public static Vector128 SelectWhereFalse(Vector128 selector, Vector128 vector)
where T : struct where U : struct
=> AndNot(selector.As(), vector);
diff --git a/sources/MathSharp/Vector/Shared/IsSupported.cs b/sources/MathSharp/Vector/Shared/IsSupported.cs
index 601d1f4..c611e07 100644
--- a/sources/MathSharp/Vector/Shared/IsSupported.cs
+++ b/sources/MathSharp/Vector/Shared/IsSupported.cs
@@ -71,7 +71,7 @@ public static bool IsHwAccelerated(VectorSize vectorSize)
return vectorSize switch
{
VectorSize.V64 => false,
- VectorSize.V128 => Sse.IsSupported,
+ VectorSize.V128 => Sse.IsSupported /* || AdvSimd.IsSupported */,
VectorSize.V256 => Avx.IsSupported
};
}
diff --git a/sources/MathSharp/Vector/VectorFloatingPoint/VectorConstants.cs b/sources/MathSharp/Vector/VectorFloatingPoint/VectorConstants.cs
index d04fdb4..9054a52 100644
--- a/sources/MathSharp/Vector/VectorFloatingPoint/VectorConstants.cs
+++ b/sources/MathSharp/Vector/VectorFloatingPoint/VectorConstants.cs
@@ -61,39 +61,42 @@ public static Vector128 AllBitsSet
}
}
- public static readonly Vector128 MaskSign = Vector128.Create(int.MaxValue).AsSingle();
- public static readonly Vector128 MaskNotSign = Vector128.Create(~int.MaxValue).AsSingle();
+ public static Vector128 MaskSign => Vector128.Create(int.MinValue).AsSingle();
+ //{
+ // get { var i = int.MinValue; return Avx2.BroadcastScalarToVector128(&i).AsSingle(); }
+ //}
+ public static Vector128 MaskNotSign => Vector128.Create(~int.MaxValue).AsSingle();
// ReSharper disable InconsistentNaming
- public static readonly Vector128 MaskNotSignXZ = Vector128.Create(~int.MaxValue, 0, ~int.MaxValue, 0).AsSingle();
- public static readonly Vector128 MaskNotSignYW = Vector128.Create(0, ~int.MaxValue, 0, ~int.MaxValue).AsSingle();
+ public static Vector128 MaskNotSignXZ => Vector128.Create(~int.MaxValue, 0, ~int.MaxValue, 0).AsSingle();
+ public static Vector128 MaskNotSignYW => Vector128.Create(0, ~int.MaxValue, 0, ~int.MaxValue).AsSingle();
- public static readonly Vector128 MaskX = Vector128.Create(+0, -1, -1, -1).AsSingle();
- public static readonly Vector128 MaskY = Vector128.Create(-1, +0, -1, -1).AsSingle();
- public static readonly Vector128 MaskZ = Vector128.Create(-1, -1, +0, -1).AsSingle();
- public static readonly Vector128 MaskW = Vector128.Create(-1, -1, -1, +0).AsSingle();
+ public static Vector128 MaskX => Vector128.Create(+0, -1, -1, -1).AsSingle();
+ public static Vector128 MaskY => Vector128.Create(-1, +0, -1, -1).AsSingle();
+ public static Vector128 MaskZ => Vector128.Create(-1, -1, +0, -1).AsSingle();
+ public static Vector128 MaskW => Vector128.Create(-1, -1, -1, +0).AsSingle();
- public static readonly Vector128 MaskXY = Vector128.Create(+0, +0, -1, -1).AsSingle();
- public static readonly Vector128 MaskZW = Vector128.Create(-1, -1, +0, +0).AsSingle();
+ public static Vector128 MaskXY => Vector128.Create(+0, +0, -1, -1).AsSingle();
+ public static Vector128 MaskZW => Vector128.Create(-1, -1, +0, +0).AsSingle();
- public static readonly Vector128 MaskXYZ = Vector128.Create(+0, +0, +0, -1).AsSingle();
- public static readonly Vector128 MaskYZW = Vector128.Create(-1, +0, +0, +0).AsSingle();
+ public static Vector128 MaskXYZ => Vector128.Create(+0, +0, +0, -1).AsSingle();
+ public static Vector128 MaskYZW => Vector128.Create(-1, +0, +0, +0).AsSingle();
- public static readonly Vector128 MaskXYZW = Vector128.Create(0).AsSingle();
+ public static Vector128 MaskXYZW => Vector128.Create(0).AsSingle();
// ReSharper restore InconsistentNaming
- public static readonly Vector128 UnitX = Vector128.Create(1f, 0f, 0f, 0f);
- public static readonly Vector128 UnitY = Vector128.Create(0f, 1f, 0f, 0f);
- public static readonly Vector128 UnitZ = Vector128.Create(0f, 0f, 1f, 0f);
- public static readonly Vector128 UnitW = Vector128.Create(0f, 0f, 0f, 1f);
-
- public static readonly Vector128 OneDivPi = Vector128.Create(ScalarSingleConstants.OneDivPi);
- public static readonly Vector128 OneDiv2Pi = Vector128.Create(ScalarSingleConstants.OneDiv2Pi);
- public static readonly Vector128 Pi2 = Vector128.Create(ScalarSingleConstants.Pi2);
- public static readonly Vector128 Pi = Vector128.Create(ScalarSingleConstants.Pi);
- public static readonly Vector128 PiDiv2 = Vector128.Create(ScalarSingleConstants.PiDiv2);
- public static readonly Vector128