---
title: "Vector and quaternion math in C#"
url: https://recursiveai.org/onemath/cookbook/vector-and-quaternion-math/
description: "Vector, matrix and quaternion math in C# that gives the same bits on every machine: dot and cross products, normalize, rotate with a quaternion, slerp, and transform points with a matrix. Runnable code, with OneMath."
version: "1.0.0"
---

# Vector and quaternion math in C#

OneMath has `Vector2/3/4`, `Matrix3x3/4x4` and `Quaternion` types in float (`F`) and double (`D`), with the operations you expect and the same results on every machine. The program below takes a ship’s heading, turns it with a quaternion, blends two orientations and moves a point into world space.

```shell
dotnet new console -o VectorMath && cd VectorMath
dotnet add package RecursiveAI.OneMath --version 1.0.0
```

Put this in `Program.cs` and run `dotnet run`:

```csharp
using RecursiveAI.OneMath;

var forward = new Vector3F(0, 0, 1);
var toTarget = new Vector3F(3, 0, 4);

// Vectors: length, normalize, dot and cross products, distance.
Vector3F dir = toTarget.Normalized();
Console.WriteLine($"length {toTarget.Length()}, direction {dir}");
Console.WriteLine($"dot {Vector3F.Dot(forward, dir)}");
Console.WriteLine($"cross {Vector3F.Cross(forward, dir)}");
Console.WriteLine($"distance {Vector3F.Distance(Vector3F.Zero, toTarget)}");

// Quaternions: turn 90 degrees about the up axis (counterclockwise seen from above).
QuaternionF turn = QuaternionF.CreateFromAxisAngle(Vector3F.UnitY, MathF.PI / 2);
Console.WriteLine($"forward turned: {turn.Rotate(forward)}");

// Blend two orientations: halfway along the shortest arc.
QuaternionF half = QuaternionF.Slerp(QuaternionF.Identity, turn, 0.5f);
Console.WriteLine($"halfway: {half.Rotate(forward)}");

// Combine rotations: a * b applies b first, then a.
QuaternionF twice = turn * turn;
Console.WriteLine($"turned twice: {twice.Rotate(forward)}");

// Matrices: rotate, then move 10 along x. Column vectors, so read right to left.
Matrix4x4F world = Matrix4x4F.CreateTranslation(new Vector3F(10, 0, 0))
                 * Matrix4x4F.CreateFromQuaternion(turn);
Console.WriteLine($"local (0, 0, 1) in world: {world.TransformPoint(forward)}");
```

```text
length 5, direction (0.6, 0, 0.8)
dot 0.8
cross (0, 0.6, 0)
distance 5
forward turned: (0.99999994, 0, 5.9604645E-08)
halfway: (0.70710695, 0, 0.7071067)
turned twice: (0, 0, -0.99999976)
local (0, 0, 1) in world: (11, 0, 5.9604645E-08)
```

`0.99999994` and `5.9604645E-08` instead of 1 and 0 are float rounding: π/2 isn’t exact in a `float`, and neither are its sine and cosine. What OneMath promises is that every machine prints these same values.

## The types

- **Vectors:** `Vector2F`, `Vector3F`, `Vector4F` and their `D` forms, with `+ - *`, `Dot`, `Cross`, `Length`, `Normalized`, `Distance`, `Lerp`, `Min`, `Max` and `Abs`.
- **Quaternions:** `CreateFromAxisAngle` (the axis must be a unit vector), `Rotate`, `Slerp`, `NLerp`, `Conjugated`, `Normalized` and the Hamilton product `a * b`.
- **Matrices:** `Matrix2x2`, `Matrix3x3`, `Matrix4x4`, with `CreateTranslation`, `CreateRotationX/Y/Z`, `CreateFromQuaternion`, `TransformPoint` and `TransformVector`; also `Affine3`, `RigidTransform` and `Bounds2/3`.
- `ToSystemNumerics()` and `FromSystemNumerics()` convert to and from System.Numerics, for handing results to a renderer.

## Limits

- **Column vectors.** `A * B` applies `B` first, the opposite of System.Numerics and MonoGame. Moving existing code: [Port System.Numerics code to OneMath](https://recursiveai.org/onemath/cookbook/port-from-system-numerics/).
- **Exact equality is exact.** `==` compares bits; use a tolerance when comparing results that went through different operations.

Why the results match across machines, and how to check it: [Deterministic floating-point math in C#](https://recursiveai.org/onemath/cookbook/check-machines-agree/).
