From 17cea2f6126bc94ae986d256c231b42c0f390063 Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 12:43:44 -0500 Subject: [PATCH 1/8] update: drop support for net48 in favor of netstandard2.1 - bumped LangVersion to 11.0 - added basic AGENTS.md +semver: breaking --- AGENTS.md | 38 +++++++++++++++++++ src/FixedMathSharp/FixedMathSharp.csproj | 4 +- .../FixedMathSharp.Tests.csproj | 5 ++- 3 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..60ed110 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,38 @@ +# FixedMathSharp agent instructions + +## Project intent and architecture +- This repository is a deterministic fixed-point math library centered on `Fixed64` (`src/FixedMathSharp/Numerics/Fixed64.cs`) with Q32.32 representation (`SHIFT_AMOUNT_I = 32` in `src/FixedMathSharp/Core/FixedMath.cs`). +- Most API surface lives in value-type numerics (`Fixed64`, `Vector2d`, `Vector3d`, `FixedQuaternion`, `Fixed3x3`, `Fixed4x4`) plus bounds types (`BoundingBox`, `BoundingSphere`, `BoundingArea`) implementing `IBound`. +- Keep operations deterministic and allocation-light; many methods use `m_rawValue` and `[MethodImpl(MethodImplOptions.AggressiveInlining)]` for hot paths. +- `FixedMath` and `FixedTrigonometry` are the shared algorithm backbones; extension classes in `src/FixedMathSharp/Numerics/Extensions/` are thin forwarding wrappers, not alternate implementations. + +## Build and test workflows +- Solution: `FixedMathSharp.sln` with library project and test project. +- Target frameworks are multi-targeted in both projects: `net48;net8`. +- Typical local workflow: + - `dotnet restore` + - `dotnet build --configuration Debug --no-restore` + - `dotnet test --configuration Debug` +- CI detail from `.github/workflows/dotnet.yml`: + - Linux runs `net48` tests via Mono + `xunit.console.exe` and `net8` via `dotnet test -f net8`. + - Windows runs `dotnet test` for both TFMs. +- Packaging/versioning comes from `src/FixedMathSharp/FixedMathSharp.csproj`: GitVersion variables are consumed when present, otherwise version falls back to `0.0.0`. + +## Code conventions specific to this repo +- Prefer `Fixed64` constants (`Fixed64.Zero`, `Fixed64.One`, `FixedMath.PI`) over primitive literals in math-heavy code. +- Preserve saturating/guarded semantics in operators and math helpers (for example `Fixed64` add/sub overflow behavior). +- When touching bounds logic, maintain cross-type dispatch shape in `Intersects(IBound)` and shared clamping projection via `IBoundExtensions.ProjectPointWithinBounds`. +- Serialization compatibility is intentional: + - MessagePack attributes on serializable structs (`[MessagePackObject]`, `[Key]`) across TFMs. + - Conditional serializers in tests (`BinaryFormatter` for `NET48`, `System.Text.Json` for `NET8`). +- `ThreadLocalRandom` is marked `[Obsolete]`; new deterministic RNG work should prefer `DeterministicRandom` and `DeterministicRandom.FromWorldFeature(...)` in `src/FixedMathSharp/Utility/DeterministicRandom.cs`. + +## Testing patterns to mirror +- Tests are xUnit (`tests/FixedMathSharp.Tests`). Keep one feature area per test file (e.g., `Vector3d.Tests.cs`, `Bounds/BoundingBox.Tests.cs`). +- Use helper assertions from `tests/FixedMathSharp.Tests/Support/FixedMathTestHelper.cs` for tolerance/range checks rather than ad-hoc epsilon logic. +- For deterministic RNG changes, validate same-seed reproducibility and bounds/argument exceptions like in `DeterministicRandom.Tests.cs`. + +## Agent editing guidance +- Keep public API shape stable unless the task explicitly requests API changes. +- Match existing style (regions, XML docs, explicit namespaces, no implicit usings). +- Make focused edits in the relevant numeric/bounds module and update corresponding tests in the parallel test file. \ No newline at end of file diff --git a/src/FixedMathSharp/FixedMathSharp.csproj b/src/FixedMathSharp/FixedMathSharp.csproj index 9b5279c..7b10818 100644 --- a/src/FixedMathSharp/FixedMathSharp.csproj +++ b/src/FixedMathSharp/FixedMathSharp.csproj @@ -2,8 +2,8 @@ - 9.0 - net48;net8 + 11.0 + netstandard2.1;net8 $(GitVersion_FullSemVer) diff --git a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj index cf4680b..f1a2630 100644 --- a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj +++ b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj @@ -1,12 +1,13 @@  - 9.0 - net48;net8 + 11.0 + net8 disable enable false true Debug;Release + Exe From cdceb0a53f40f9cbb13534c612d47dff060899c0 Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 12:45:19 -0500 Subject: [PATCH 2/8] update: drop MessagePack support in favor of MemoryPack +semver: breaking --- src/FixedMathSharp/Bounds/BoundingArea.cs | 39 ++-- src/FixedMathSharp/Bounds/BoundingBox.cs | 170 +++++++++--------- src/FixedMathSharp/Bounds/BoundingSphere.cs | 25 +-- src/FixedMathSharp/Core/FixedMath.cs | 2 +- src/FixedMathSharp/Core/FixedTrigonometry.cs | 2 +- src/FixedMathSharp/FixedMathSharp.csproj | 2 +- .../Numerics/Extensions/Fixed64.Extensions.cs | 4 +- src/FixedMathSharp/Numerics/Fixed3x3.cs | 29 ++- src/FixedMathSharp/Numerics/Fixed4x4.cs | 52 +++--- src/FixedMathSharp/Numerics/Fixed64.cs | 8 +- src/FixedMathSharp/Numerics/FixedCurve.cs | 14 +- src/FixedMathSharp/Numerics/FixedCurveKey.cs | 23 +-- .../Numerics/FixedQuaternion.cs | 26 +-- src/FixedMathSharp/Numerics/FixedRange.cs | 14 +- src/FixedMathSharp/Numerics/Vector2d.cs | 28 +-- src/FixedMathSharp/Numerics/Vector3d.cs | 30 ++-- .../Utility/DeterministicRandom.cs | 6 +- .../Bounds/BoundingArea.Tests.cs | 28 +-- .../Bounds/BoundingBox.Tests.cs | 32 +--- .../Bounds/BoundingSphere.Tests.cs | 28 +-- .../DeterministicRandom.Tests.cs | 5 +- tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs | 28 +-- tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs | 31 +--- tests/FixedMathSharp.Tests/Fixed64.Tests.cs | 32 +--- tests/FixedMathSharp.Tests/FixedCurveTests.cs | 29 +-- .../FixedMathSharp.Tests.csproj | 16 +- .../FixedQuanternion.Tests.cs | 32 +--- .../FixedMathSharp.Tests/FixedRange.Tests.cs | 27 +-- .../Support/FixedMathTestHelper.cs | 12 +- tests/FixedMathSharp.Tests/Vector2d.Tests.cs | 27 +-- tests/FixedMathSharp.Tests/Vector3d.Tests.cs | 32 +--- 31 files changed, 287 insertions(+), 546 deletions(-) diff --git a/src/FixedMathSharp/Bounds/BoundingArea.cs b/src/FixedMathSharp/Bounds/BoundingArea.cs index d105df8..b526ec3 100644 --- a/src/FixedMathSharp/Bounds/BoundingArea.cs +++ b/src/FixedMathSharp/Bounds/BoundingArea.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; @@ -18,21 +18,21 @@ namespace FixedMathSharp /// [Serializable] - [MessagePackObject] - public struct BoundingArea : IBound, IEquatable + [MemoryPackable] + public partial struct BoundingArea : IBound, IEquatable { #region Fields /// /// One of the corner points of the bounding area. /// - [Key(0)] + [MemoryPackOrder(0)] public Vector3d Corner1; /// /// The opposite corner point of the bounding area. /// - [Key(1)] + [MemoryPackOrder(1)] public Vector3d Corner2; #endregion @@ -68,7 +68,7 @@ public BoundingArea(Vector3d corner1, Vector3d corner2) /// /// The minimum corner of the bounding box. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Min { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -78,49 +78,49 @@ public Vector3d Min /// /// The maximum corner of the bounding box. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Max { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new(MaxX, MaxY, MaxZ); } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MinX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Corner1.x < Corner2.x ? Corner1.x : Corner2.x; } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MaxX { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Corner1.x > Corner2.x ? Corner1.x : Corner2.x; } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MinY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Corner1.y < Corner2.y ? Corner1.y : Corner2.y; } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MaxY { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Corner1.y > Corner2.y ? Corner1.y : Corner2.y; } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MinZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Corner1.z < Corner2.z ? Corner1.z : Corner2.z; } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MaxZ { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -130,7 +130,7 @@ public Fixed64 MaxZ /// /// Calculates the width (X-axis) of the bounding area. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Width { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -140,7 +140,7 @@ public Fixed64 Width /// /// Calculates the height (Y-axis) of the bounding area. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Height { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -150,7 +150,7 @@ public Fixed64 Height /// /// Calculates the depth (Z-axis) of the bounding area. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Depth { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -163,8 +163,8 @@ public Fixed64 Depth public bool Contains(Vector3d point) { // Check if the point is within the bounds of the area (including boundaries) - return point.x >= MinX && point.x <= MaxX - && point.y >= MinY && point.y <= MaxY + return point.x >= MinX && point.x <= MaxX + && point.y >= MinY && point.y <= MaxY && point.z >= MinZ && point.z <= MaxZ; } @@ -208,7 +208,8 @@ public bool Intersects(IBound other) return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius; default: return false; // Default case for unknown or unsupported types - }; + } + ; } /// diff --git a/src/FixedMathSharp/Bounds/BoundingBox.cs b/src/FixedMathSharp/Bounds/BoundingBox.cs index 1ee044e..d93c666 100644 --- a/src/FixedMathSharp/Bounds/BoundingBox.cs +++ b/src/FixedMathSharp/Bounds/BoundingBox.cs @@ -1,7 +1,6 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; -using System.Runtime.Serialization; #if NET8_0_OR_GREATER using System.Text.Json.Serialization; @@ -22,7 +21,7 @@ namespace FixedMathSharp /// - Supports more precise intersection tests than BoundingArea, making it ideal for detailed spatial queries. /// [Serializable] - [MessagePackObject(AllowPrivate = true)] + [MemoryPackable] public partial struct BoundingBox : IBound, IEquatable { #region Fields @@ -30,25 +29,28 @@ public partial struct BoundingBox : IBound, IEquatable /// /// The minimum corner of the bounding box. /// - [Key(0)] - private Vector3d _min; + [MemoryPackOrder(0)] + public Vector3d Min { get; private set; } /// /// The maximum corner of the bounding box. /// - [Key(1)] - private Vector3d _max; + [MemoryPackOrder(1)] + public Vector3d Max { get; private set; } - [IgnoreMember] - private bool _isDirty; + /// + /// + /// + [MemoryPackOrder(2)] + public byte Version { get; private set; } - [Key(2)] - private byte _version; + [MemoryPackIgnore] + private bool _isDirty; /// /// Vertices of the bounding box. /// - [IgnoreMember] + [MemoryPackIgnore] private Vector3d[] _vertices; #endregion @@ -63,22 +65,25 @@ public BoundingBox(Vector3d center, Vector3d size) { Vector3d half = Vector3d.Abs(size) * Fixed64.Half; - _min = center - half; - _max = center + half; + Min = center - half; + Max = center + half; _vertices = new Vector3d[8]; _isDirty = true; - _version = 1; + Version = 1; } - [SerializationConstructor] +#if NET8_0_OR_GREATER + [JsonConstructor] +#endif + [MemoryPackConstructor] public BoundingBox(Vector3d min, Vector3d max, byte version) { - _min = min; - _max = max; + this.Min = min; + this.Max = max; _vertices = new Vector3d[8]; _isDirty = true; - _version = version; + this.Version = version; } #endregion @@ -88,18 +93,18 @@ public BoundingBox(Vector3d min, Vector3d max, byte version) /// /// The center of the bounding box. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Center { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (_min + _max) * Fixed64.Half; + get => (Min + Max) * Fixed64.Half; [MethodImpl(MethodImplOptions.AggressiveInlining)] set { - Vector3d half = (_max - _min) * Fixed64.Half; - _min = value - half; - _max = value + half; + Vector3d half = (Max - Min) * Fixed64.Half; + Min = value - half; + Max = value + half; _isDirty = true; } } @@ -107,19 +112,19 @@ public Vector3d Center /// /// The total size of the box (Width, Height, Depth). This is always twice the scope. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Proportions { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => _max - _min; + get => Max - Min; [MethodImpl(MethodImplOptions.AggressiveInlining)] set { Vector3d half = value * Fixed64.Half; - Vector3d center = (_min + _max) * Fixed64.Half; - _min = center - half; - _max = center + half; + Vector3d center = (Min + Max) * Fixed64.Half; + Min = center - half; + Max = center + half; _isDirty = true; } } @@ -127,23 +132,15 @@ public Vector3d Proportions /// /// The range (half-size) of the bounding box in all directions. Always half of the total size. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Scope { [MethodImpl(MethodImplOptions.AggressiveInlining)] - get => (_max - _min) * Fixed64.Half; + get => (Max - Min) * Fixed64.Half; } - /// - [IgnoreMember] - public Vector3d Min => _min; - - /// - [IgnoreMember] - public Vector3d Max => _max; - /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d[] Vertices { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -161,10 +158,10 @@ public void Orient(Vector3d center, Vector3d? size) { Vector3d half = size.HasValue ? size.Value * Fixed64.Half - : (_max - _min) * Fixed64.Half; + : (Max - Min) * Fixed64.Half; - _min = center - half; - _max = center + half; + Min = center - half; + Max = center + half; _isDirty = true; } @@ -174,10 +171,10 @@ public void Orient(Vector3d center, Vector3d? size) public void Resize(Vector3d size) { Vector3d half = size * Fixed64.Half; - Vector3d center = (_min + _max) * Fixed64.Half; + Vector3d center = (Min + Max) * Fixed64.Half; - _min = center - half; - _max = center + half; + Min = center - half; + Max = center + half; _isDirty = true; } @@ -186,8 +183,8 @@ public void Resize(Vector3d size) /// public void SetMinMax(Vector3d min, Vector3d max) { - _min = min; - _max = max; + Min = min; + Max = max; _isDirty = true; } @@ -196,8 +193,8 @@ public void SetMinMax(Vector3d min, Vector3d max) /// public void SetBoundingBox(Vector3d center, Vector3d scope) { - _min = center - scope; - _max = center + scope; + Min = center - scope; + Max = center + scope; _isDirty = true; } @@ -207,9 +204,9 @@ public void SetBoundingBox(Vector3d center, Vector3d scope) [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool Contains(Vector3d point) { - return point.x >= _min.x && point.x <= _max.x - && point.y >= _min.y && point.y <= _max.y - && point.z >= _min.z && point.z <= _max.z; + return point.x >= Min.x && point.x <= Max.x + && point.y >= Min.y && point.y <= Max.y + && point.z >= Min.z && point.z <= Max.z; } /// @@ -229,18 +226,19 @@ public bool Intersects(IBound other) return true; // Full containment // General intersection logic (allowing for overlap) - return !(_max.x <= other.Min.x || _min.x >= other.Max.x || - _max.y <= other.Min.y || _min.y >= other.Max.y || - _max.z <= other.Min.z || _min.z >= other.Max.z); + return !(Max.x <= other.Min.x || Min.x >= other.Max.x || + Max.y <= other.Min.y || Min.y >= other.Max.y || + Max.z <= other.Min.z || Min.z >= other.Max.z); } case BoundingSphere sphere: // project the sphere’s center onto the 3D volume and checks the distance to the surface. // If the distance from the closest point to the center is less than or equal to the sphere’s radius, they intersect. return Vector3d.SqrDistance(sphere.Center, this.ProjectPointWithinBounds(sphere.Center)) <= sphere.SqrRadius; - default: + default: return false; // Default case for unknown or unsupported types - }; + } + ; } /// @@ -267,10 +265,10 @@ public Vector3d ProjectPoint(Vector3d point) public Fixed64 DistanceToSurface(Vector3d point) { // Clamp the point to the nearest point on the box's surface - Vector3d clampedPoint = new Vector3d( - FixedMath.Clamp(point.x, _min.x, _max.x), - FixedMath.Clamp(point.y, _min.y, _max.y), - FixedMath.Clamp(point.z, _min.z, _max.z) + Vector3d clampedPoint = new( + FixedMath.Clamp(point.x, Min.x, Max.x), + FixedMath.Clamp(point.y, Min.y, Max.y), + FixedMath.Clamp(point.z, Min.z, Max.z) ); // If the point is inside the box, return 0 @@ -295,12 +293,12 @@ public Vector3d ClosestPointOnSurface(Vector3d point) if (Contains(point)) { // Calculate distances to each face and return the closest face. - Fixed64 distToMinX = point.x - _min.x; - Fixed64 distToMaxX = _max.x - point.x; - Fixed64 distToMinY = point.y - _min.y; - Fixed64 distToMaxY = _max.y - point.y; - Fixed64 distToMinZ = point.z - _min.z; - Fixed64 distToMaxZ = _max.z - point.z; + Fixed64 distToMinX = point.x - Min.x; + Fixed64 distToMaxX = Max.x - point.x; + Fixed64 distToMinY = point.y - Min.y; + Fixed64 distToMaxY = Max.y - point.y; + Fixed64 distToMinZ = point.z - Min.z; + Fixed64 distToMaxZ = Max.z - point.z; Fixed64 minDistToFace = FixedMath.Min(distToMinX, FixedMath.Min(distToMaxX, @@ -309,23 +307,23 @@ public Vector3d ClosestPointOnSurface(Vector3d point) FixedMath.Min(distToMinZ, distToMaxZ))))); // Adjust the closest point based on the face. - if (minDistToFace == distToMinX) point.x = _min.x; - else if (minDistToFace == distToMaxX) point.x = _max.x; + if (minDistToFace == distToMinX) point.x = Min.x; + else if (minDistToFace == distToMaxX) point.x = Max.x; - if (minDistToFace == distToMinY) point.y = _min.y; - else if (minDistToFace == distToMaxY) point.y = _max.y; + if (minDistToFace == distToMinY) point.y = Min.y; + else if (minDistToFace == distToMaxY) point.y = Max.y; - if (minDistToFace == distToMinZ) point.z = _min.z; - else if (minDistToFace == distToMaxZ) point.z = _max.z; + if (minDistToFace == distToMinZ) point.z = Min.z; + else if (minDistToFace == distToMaxZ) point.z = Max.z; return point; } // If the point is outside the box, clamp to the nearest surface. return new Vector3d( - FixedMath.Clamp(point.x, _min.x, _max.x), - FixedMath.Clamp(point.y, _min.y, _max.y), - FixedMath.Clamp(point.z, _min.z, _max.z) + FixedMath.Clamp(point.x, Min.x, Max.x), + FixedMath.Clamp(point.y, Min.y, Max.y), + FixedMath.Clamp(point.z, Min.z, Max.z) ); } @@ -364,8 +362,8 @@ private Vector3d[] GetOrGenerateVertices() if (_isDirty) { - Vector3d min = _min; - Vector3d max = _max; + Vector3d min = Min; + Vector3d max = Max; _vertices[0] = new(min.x, min.y, min.z); _vertices[1] = new(max.x, min.y, min.z); @@ -393,8 +391,8 @@ public static BoundingBox Union(BoundingBox a, BoundingBox b) { return new BoundingBox { - _min = Vector3d.Min(a._min, b._min), - _max = Vector3d.Max(a._max, b._max), + Min = Vector3d.Min(a.Min, b.Min), + Max = Vector3d.Max(a.Max, b.Max), _isDirty = true }; } @@ -435,17 +433,11 @@ public static Vector3d FindClosestPointsBetweenBoxes(BoundingBox a, BoundingBox public override bool Equals(object? obj) => obj is BoundingBox other && Equals(other); public bool Equals(BoundingBox other) - => _min.Equals(other._min) && _max.Equals(other._max); + => Min.Equals(other.Min) && Max.Equals(other.Max); public override int GetHashCode() { - unchecked - { - int hash = 17; - hash = hash * 23 + _min.GetHashCode(); - hash = hash * 23 + _max.GetHashCode(); - return hash; - } + return HashCode.Combine(Min, Max); } #endregion diff --git a/src/FixedMathSharp/Bounds/BoundingSphere.cs b/src/FixedMathSharp/Bounds/BoundingSphere.cs index 6c633de..df13653 100644 --- a/src/FixedMathSharp/Bounds/BoundingSphere.cs +++ b/src/FixedMathSharp/Bounds/BoundingSphere.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; @@ -17,21 +17,21 @@ namespace FixedMathSharp /// - Suitable for encapsulating objects with roughly spherical shapes or objects that rotate frequently, where the bounding box may need constant updates. /// [Serializable] - [MessagePackObject] - public struct BoundingSphere : IBound, IEquatable + [MemoryPackable] + public partial struct BoundingSphere : IBound, IEquatable { #region Fields /// /// The center point of the sphere. /// - [Key(0)] + [MemoryPackOrder(0)] public Vector3d Center; /// /// The radius of the sphere. /// - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 Radius; #endregion @@ -52,14 +52,14 @@ public BoundingSphere(Vector3d center, Fixed64 radius) #region Properties and Methods (Instance) - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Min { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => Center - new Vector3d(Radius, Radius, Radius); } - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Max { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -69,7 +69,7 @@ public Vector3d Max /// /// The squared radius of the sphere. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 SqrRadius { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -96,9 +96,9 @@ public bool Intersects(IBound other) switch (other) { case BoundingBox or BoundingArea: - // Find the closest point on the BoundingArea to the sphere's center - // Check if the closest point is within the sphere's radius - return Vector3d.SqrDistance(Center, other.ProjectPointWithinBounds(Center)) <= SqrRadius; + // Find the closest point on the BoundingArea to the sphere's center + // Check if the closest point is within the sphere's radius + return Vector3d.SqrDistance(Center, other.ProjectPointWithinBounds(Center)) <= SqrRadius; case BoundingSphere otherSphere: { Fixed64 distanceSquared = Vector3d.SqrDistance(Center, otherSphere.Center); @@ -107,7 +107,8 @@ public bool Intersects(IBound other) } default: return false; // Default case for unknown or unsupported types - }; + } + ; } /// diff --git a/src/FixedMathSharp/Core/FixedMath.cs b/src/FixedMathSharp/Core/FixedMath.cs index ea4ce81..19a3878 100644 --- a/src/FixedMathSharp/Core/FixedMath.cs +++ b/src/FixedMathSharp/Core/FixedMath.cs @@ -15,7 +15,7 @@ public static partial class FixedMath public const int SHIFT_AMOUNT_I = 32; public const uint MAX_SHIFTED_AMOUNT_UI = (uint)((1L << SHIFT_AMOUNT_I) - 1); public const ulong MASK_UL = (ulong)(ulong.MaxValue << SHIFT_AMOUNT_I); - + public const long MAX_VALUE_L = long.MaxValue; // Max possible value for Fixed64 public const long MIN_VALUE_L = long.MinValue; // Min possible value for Fixed64 diff --git a/src/FixedMathSharp/Core/FixedTrigonometry.cs b/src/FixedMathSharp/Core/FixedTrigonometry.cs index 71839b1..c9f6120 100644 --- a/src/FixedMathSharp/Core/FixedTrigonometry.cs +++ b/src/FixedMathSharp/Core/FixedTrigonometry.cs @@ -340,7 +340,7 @@ public static Fixed64 Sin(Fixed64 x) /// - The function automatically normalizes input values to the range [-π, π] for stability. /// public static Fixed64 Cos(Fixed64 x) - { + { long xl = x.m_rawValue; long rawAngle = xl + (xl > 0 ? -PI.m_rawValue - PiOver2.m_rawValue : PiOver2.m_rawValue); return Sin(Fixed64.FromRaw(rawAngle)); diff --git a/src/FixedMathSharp/FixedMathSharp.csproj b/src/FixedMathSharp/FixedMathSharp.csproj index 7b10818..56b864f 100644 --- a/src/FixedMathSharp/FixedMathSharp.csproj +++ b/src/FixedMathSharp/FixedMathSharp.csproj @@ -67,7 +67,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/src/FixedMathSharp/Numerics/Extensions/Fixed64.Extensions.cs b/src/FixedMathSharp/Numerics/Extensions/Fixed64.Extensions.cs index cc8ac7e..ddba6f6 100644 --- a/src/FixedMathSharp/Numerics/Extensions/Fixed64.Extensions.cs +++ b/src/FixedMathSharp/Numerics/Extensions/Fixed64.Extensions.cs @@ -1,7 +1,5 @@ using System; using System.Runtime.CompilerServices; -using System.Threading.Tasks; -using static System.Net.Mime.MediaTypeNames; namespace FixedMathSharp { @@ -22,7 +20,7 @@ public static bool IsInteger(this Fixed64 value) { return Fixed64.IsInteger(value); } - + /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Fixed64 Squared(this Fixed64 value) diff --git a/src/FixedMathSharp/Numerics/Fixed3x3.cs b/src/FixedMathSharp/Numerics/Fixed3x3.cs index baad605..d7a8103 100644 --- a/src/FixedMathSharp/Numerics/Fixed3x3.cs +++ b/src/FixedMathSharp/Numerics/Fixed3x3.cs @@ -1,6 +1,5 @@ -using MessagePack; +using MemoryPack; using System; -using System.Drawing.Drawing2D; using System.Runtime.CompilerServices; namespace FixedMathSharp @@ -20,36 +19,36 @@ namespace FixedMathSharp /// - Useful when optimizing transformations, as it omits the overhead of translation and perspective. /// [Serializable] - [MessagePackObject] - public struct Fixed3x3 : IEquatable + [MemoryPackable] + public partial struct Fixed3x3 : IEquatable { #region Fields and Constants - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 m00; - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 m01; - [Key(2)] + [MemoryPackOrder(2)] public Fixed64 m02; - [Key(3)] + [MemoryPackOrder(3)] public Fixed64 m10; - [Key(4)] + [MemoryPackOrder(4)] public Fixed64 m11; - [Key(5)] + [MemoryPackOrder(5)] public Fixed64 m12; - [Key(6)] + [MemoryPackOrder(6)] public Fixed64 m20; - [Key(7)] + [MemoryPackOrder(7)] public Fixed64 m21; - [Key(8)] + [MemoryPackOrder(8)] public Fixed64 m22; /// /// Returns the identity matrix (no scaling, rotation, or translation). /// - public static readonly Fixed3x3 Identity = new(new Vector3d(1f, 0f, 0f), new Vector3d(0f, 1f, 0f), new Vector3d(0f, 0f, 1f)); + public static readonly Fixed3x3 Identity = new(new Vector3d(1f, 0f, 0f), new Vector3d(0f, 1f, 0f), new Vector3d(0f, 0f, 1f)); /// /// Returns a matrix with all elements set to zero. @@ -89,7 +88,7 @@ Vector3d m20_m21_m22 #region Properties and Methods (Instance) - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 this[int index] { get diff --git a/src/FixedMathSharp/Numerics/Fixed4x4.cs b/src/FixedMathSharp/Numerics/Fixed4x4.cs index 1388e48..d4edfbd 100644 --- a/src/FixedMathSharp/Numerics/Fixed4x4.cs +++ b/src/FixedMathSharp/Numerics/Fixed4x4.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; @@ -19,45 +19,45 @@ namespace FixedMathSharp /// - Useful in animation, physics engines, and 3D rendering for full transformation control. /// [Serializable] - [MessagePackObject] - public struct Fixed4x4 : IEquatable + [MemoryPackable] + public partial struct Fixed4x4 : IEquatable { #region Fields and Constants - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 m00; - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 m01; - [Key(2)] + [MemoryPackOrder(2)] public Fixed64 m02; - [Key(3)] + [MemoryPackOrder(3)] public Fixed64 m03; - [Key(4)] + [MemoryPackOrder(4)] public Fixed64 m10; - [Key(5)] + [MemoryPackOrder(5)] public Fixed64 m11; - [Key(6)] + [MemoryPackOrder(6)] public Fixed64 m12; - [Key(7)] + [MemoryPackOrder(7)] public Fixed64 m13; - [Key(8)] + [MemoryPackOrder(8)] public Fixed64 m20; - [Key(9)] + [MemoryPackOrder(9)] public Fixed64 m21; - [Key(10)] + [MemoryPackOrder(10)] public Fixed64 m22; - [Key(11)] + [MemoryPackOrder(11)] public Fixed64 m23; - [Key(12)] + [MemoryPackOrder(12)] public Fixed64 m30; - [Key(13)] + [MemoryPackOrder(13)] public Fixed64 m31; - [Key(14)] + [MemoryPackOrder(14)] public Fixed64 m32; - [Key(15)] + [MemoryPackOrder(15)] public Fixed64 m33; /// @@ -77,7 +77,7 @@ public struct Fixed4x4 : IEquatable Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero, Fixed64.Zero); - + #endregion #region Constructors @@ -103,25 +103,25 @@ public Fixed4x4( #region Properties and Methods (Instance) - [IgnoreMember] + [MemoryPackIgnore] public readonly bool IsAffine => (m33 == Fixed64.One) && (m03 == Fixed64.Zero && m13 == Fixed64.Zero && m23 == Fixed64.Zero); /// - [IgnoreMember] + [MemoryPackIgnore] public readonly Vector3d Translation => ExtractTranslation(this); - [IgnoreMember] + [MemoryPackIgnore] public readonly Vector3d Up => ExtractUp(this); /// - [IgnoreMember] + [MemoryPackIgnore] public readonly Vector3d Scale => ExtractScale(this); /// - [IgnoreMember] + [MemoryPackIgnore] public readonly FixedQuaternion Rotation => ExtractRotation(this); - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 this[int index] { get diff --git a/src/FixedMathSharp/Numerics/Fixed64.cs b/src/FixedMathSharp/Numerics/Fixed64.cs index f066842..79e2e95 100644 --- a/src/FixedMathSharp/Numerics/Fixed64.cs +++ b/src/FixedMathSharp/Numerics/Fixed64.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Collections.Generic; using System.Globalization; @@ -13,7 +13,7 @@ namespace FixedMathSharp /// The precision is determined by SHIFT_AMOUNT, which defines the resolution of fractional values. /// [Serializable] - [MessagePackObject] + [MemoryPackable] public partial struct Fixed64 : IEquatable, IComparable, IEqualityComparer { #region Fields and Constants @@ -21,7 +21,7 @@ public partial struct Fixed64 : IEquatable, IComparable, IEqua /// /// The underlying raw long value representing the fixed-point number. /// - [Key(0)] + [MemoryPackOrder(0)] public long m_rawValue; public static readonly Fixed64 MAX_VALUE = new Fixed64(FixedMath.MAX_VALUE_L); @@ -153,7 +153,7 @@ public static int Sign(Fixed64 value) // Return the sign of the value, optimizing for branchless comparison return value.m_rawValue < 0 ? -1 : (value.m_rawValue > 0 ? 1 : 0); } - + /// /// Returns true if the number has no decimal part (i.e., if the number is equivalent to an integer) and False otherwise. /// diff --git a/src/FixedMathSharp/Numerics/FixedCurve.cs b/src/FixedMathSharp/Numerics/FixedCurve.cs index 2468cba..631eedd 100644 --- a/src/FixedMathSharp/Numerics/FixedCurve.cs +++ b/src/FixedMathSharp/Numerics/FixedCurve.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Linq; @@ -31,13 +31,13 @@ public enum FixedCurveMode /// Used for animations, physics calculations, and procedural data. /// [Serializable] - [MessagePackObject] - public class FixedCurve : IEquatable + [MemoryPackable] + public partial class FixedCurve : IEquatable { - [Key(0)] + [MemoryPackOrder(0)] public FixedCurveMode Mode { get; private set; } - [Key(1)] + [MemoryPackOrder(1)] public FixedCurveKey[] Keyframes { get; private set; } /// @@ -55,7 +55,7 @@ public FixedCurve(params FixedCurveKey[] keyframes) #if NET8_0_OR_GREATER [JsonConstructor] #endif - [SerializationConstructor] + [MemoryPackConstructor] public FixedCurve(FixedCurveMode mode, params FixedCurveKey[] keyframes) { Keyframes = keyframes.OrderBy(k => k.Time).ToArray(); @@ -73,7 +73,7 @@ public Fixed64 Evaluate(Fixed64 time) // Clamp input within the keyframe range if (time <= Keyframes[0].Time) return Keyframes[0].Value; - if (time >= Keyframes[Keyframes.Length - 1].Time) return Keyframes[Keyframes.Length - 1].Value; + if (time >= Keyframes[^1].Time) return Keyframes[^1].Value; // Find the surrounding keyframes for (int i = 0; i < Keyframes.Length - 1; i++) diff --git a/src/FixedMathSharp/Numerics/FixedCurveKey.cs b/src/FixedMathSharp/Numerics/FixedCurveKey.cs index b59a9a1..cf70ee3 100644 --- a/src/FixedMathSharp/Numerics/FixedCurveKey.cs +++ b/src/FixedMathSharp/Numerics/FixedCurveKey.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; #if NET8_0_OR_GREATER @@ -11,23 +11,23 @@ namespace FixedMathSharp /// Represents a keyframe in a , defining a value at a specific time. /// [Serializable] - [MessagePackObject] - public struct FixedCurveKey : IEquatable + [MemoryPackable] + public partial struct FixedCurveKey : IEquatable { /// The time at which this keyframe occurs. - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 Time; /// The value of the curve at this keyframe. - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 Value; /// The incoming tangent for cubic interpolation. - [Key(2)] + [MemoryPackOrder(2)] public Fixed64 InTangent; /// The outgoing tangent for cubic interpolation. - [Key(3)] + [MemoryPackOrder(3)] public Fixed64 OutTangent; /// @@ -74,14 +74,7 @@ public bool Equals(FixedCurveKey other) public override int GetHashCode() { - unchecked - { - int hash = Time.GetHashCode(); - hash = (hash * 31) ^ Value.GetHashCode(); - hash = (hash * 31) ^ InTangent.GetHashCode(); - hash = (hash * 31) ^ OutTangent.GetHashCode(); - return hash; - } + return HashCode.Combine(Time, Value, InTangent, OutTangent); } public static bool operator ==(FixedCurveKey left, FixedCurveKey right) => left.Equals(right); diff --git a/src/FixedMathSharp/Numerics/FixedQuaternion.cs b/src/FixedMathSharp/Numerics/FixedQuaternion.cs index 81e108d..3618472 100644 --- a/src/FixedMathSharp/Numerics/FixedQuaternion.cs +++ b/src/FixedMathSharp/Numerics/FixedQuaternion.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; @@ -9,21 +9,21 @@ namespace FixedMathSharp /// Quaternions are useful for representing rotations and can be used to perform smooth rotations and avoid gimbal lock. /// [Serializable] - [MessagePackObject] - public struct FixedQuaternion : IEquatable + [MemoryPackable] + public partial struct FixedQuaternion : IEquatable { #region Fields and Constants - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 x; - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 y; - [Key(2)] + [MemoryPackOrder(2)] public Fixed64 z; - [Key(3)] + [MemoryPackOrder(3)] public Fixed64 w; /// @@ -59,7 +59,7 @@ public FixedQuaternion(Fixed64 x, Fixed64 y, Fixed64 z, Fixed64 w) /// /// Normalized version of this quaternion. /// - [IgnoreMember] + [MemoryPackIgnore] public FixedQuaternion Normal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -69,7 +69,7 @@ public FixedQuaternion Normal /// /// Returns the Euler angles (in degrees) of this quaternion. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d EulerAngles { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -78,7 +78,7 @@ public Vector3d EulerAngles set => this = FromEulerAnglesInDegrees(value.x, value.y, value.z); } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -372,7 +372,7 @@ public static FixedQuaternion FromAxisAngle(Vector3d axis, Fixed64 angle) // Check if the angle is in a valid range (-pi, pi) if (angle < -FixedMath.PI || angle > FixedMath.PI) - throw new ArgumentOutOfRangeException("Angle must be in the range (-pi, pi)"); + throw new ArgumentOutOfRangeException($"Angle must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {angle}"); Fixed64 halfAngle = angle / Fixed64.Two; // Half-angle formula Fixed64 sinHalfAngle = FixedMath.Sin(halfAngle); @@ -412,7 +412,7 @@ public static FixedQuaternion FromEulerAngles(Fixed64 pitch, Fixed64 yaw, Fixed6 yaw < -FixedMath.PI || yaw > FixedMath.PI || roll < -FixedMath.PI || roll > FixedMath.PI) { - throw new ArgumentOutOfRangeException("Euler angles must be in the range (-pi, pi)"); + throw new ArgumentOutOfRangeException($"Euler angles must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but were ({pitch}, {yaw}, {roll})"); } Fixed64 c1 = FixedMath.Cos(yaw / Fixed64.Two); @@ -770,7 +770,7 @@ public Fixed3x3 ToMatrix3x3() #region Equality and HashCode Overrides [MethodImpl(MethodImplOptions.AggressiveInlining)] - public override bool Equals(object obj) + public override bool Equals(object? obj) { return obj is FixedQuaternion other && Equals(other); } diff --git a/src/FixedMathSharp/Numerics/FixedRange.cs b/src/FixedMathSharp/Numerics/FixedRange.cs index d5b8037..5a08f41 100644 --- a/src/FixedMathSharp/Numerics/FixedRange.cs +++ b/src/FixedMathSharp/Numerics/FixedRange.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Runtime.CompilerServices; @@ -8,8 +8,8 @@ namespace FixedMathSharp /// Represents a range of values with fixed precision. /// [Serializable] - [MessagePackObject] - public struct FixedRange : IEquatable + [MemoryPackable] + public partial struct FixedRange : IEquatable { #region Constants @@ -30,13 +30,13 @@ public struct FixedRange : IEquatable /// /// Gets the minimum value of the range. /// - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 Min; /// /// Gets the maximum value of the range. /// - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 Max; #endregion @@ -72,7 +72,7 @@ public FixedRange(Fixed64 min, Fixed64 max, bool enforceOrder = true) /// /// The length of the range, computed as Max - Min. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Length { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -82,7 +82,7 @@ public Fixed64 Length /// /// The midpoint of the range. /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 MidPoint { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/FixedMathSharp/Numerics/Vector2d.cs b/src/FixedMathSharp/Numerics/Vector2d.cs index 4b25b63..5efc393 100644 --- a/src/FixedMathSharp/Numerics/Vector2d.cs +++ b/src/FixedMathSharp/Numerics/Vector2d.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -21,7 +21,7 @@ namespace FixedMathSharp /// - Useful for fixed-point math scenarios where floating-point precision is insufficient or not desired. /// [Serializable] - [MessagePackObject] + [MemoryPackable] public partial struct Vector2d : IEquatable, IComparable, IEqualityComparer { #region Fields and Constants @@ -29,13 +29,13 @@ public partial struct Vector2d : IEquatable, IComparable, IE /// /// The X component of the vector. /// - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 x; /// /// The Y component of the vector. /// - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 y; /// @@ -105,7 +105,7 @@ public Vector2d(Fixed64 xFixed, Fixed64 yFixed) /// /// Rotates the vector to the right (90 degrees clockwise). /// - [IgnoreMember] + [MemoryPackIgnore] public Vector2d RotatedRight { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -115,7 +115,7 @@ public Vector2d RotatedRight /// /// Rotates the vector to the left (90 degrees counterclockwise). /// - [IgnoreMember] + [MemoryPackIgnore] public Vector2d RotatedLeft { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -125,7 +125,7 @@ public Vector2d RotatedLeft /// /// Gets the right-hand (counter-clockwise) normal vector. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector2d RightHandNormal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -135,7 +135,7 @@ public Vector2d RightHandNormal /// /// Gets the left-hand (clockwise) normal vector. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector2d LeftHandNormal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -143,7 +143,7 @@ public Vector2d LeftHandNormal } /// - [IgnoreMember] + [MemoryPackIgnore] public Vector2d Normal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -153,7 +153,7 @@ public Vector2d Normal /// /// Returns the actual length of this vector (RO). /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Magnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -163,7 +163,7 @@ public Fixed64 Magnitude /// /// Returns the square magnitude of the vector (avoids calculating the square root). /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 SqrMagnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -173,7 +173,7 @@ public Fixed64 SqrMagnitude /// /// Returns a long hash of the vector based on its x and y values. /// - [IgnoreMember] + [MemoryPackIgnore] public long LongStateHash { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -183,14 +183,14 @@ public long LongStateHash /// /// Returns a hash of the vector based on its state. /// - [IgnoreMember] + [MemoryPackIgnore] public int StateHash { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => (int)(LongStateHash % int.MaxValue); } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/FixedMathSharp/Numerics/Vector3d.cs b/src/FixedMathSharp/Numerics/Vector3d.cs index 1a9f6c4..21cb505 100644 --- a/src/FixedMathSharp/Numerics/Vector3d.cs +++ b/src/FixedMathSharp/Numerics/Vector3d.cs @@ -1,4 +1,4 @@ -using MessagePack; +using MemoryPack; using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -19,7 +19,7 @@ namespace FixedMathSharp /// - Essential for fixed-point math scenarios where floating-point precision isn't suitable. /// [Serializable] - [MessagePackObject] + [MemoryPackable] public partial struct Vector3d : IEquatable, IComparable, IEqualityComparer { #region Fields and Constants @@ -27,19 +27,19 @@ public partial struct Vector3d : IEquatable, IComparable, IE /// /// The X component of the vector. /// - [Key(0)] + [MemoryPackOrder(0)] public Fixed64 x; /// /// The Y component of the vector. /// - [Key(1)] + [MemoryPackOrder(1)] public Fixed64 y; /// /// The Z component of the vector. /// - [Key(2)] + [MemoryPackOrder(2)] public Fixed64 z; /// @@ -117,7 +117,7 @@ public Vector3d(Fixed64 xLong, Fixed64 yLong, Fixed64 zLong) /// Note that the positive direction of rotation is defined by the right-hand rule: /// If your right hand's thumb points in the positive Y direction, then your fingers curl in the positive direction of rotation. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d RightHandNormal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -127,7 +127,7 @@ public Vector3d RightHandNormal /// /// Provides a rotated version of the current vector, where rotation is a 90 degrees rotation around the Y axis in the clockwise direction. /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d LeftHandNormal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -135,7 +135,7 @@ public Vector3d LeftHandNormal } /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Normal { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -145,7 +145,7 @@ public Vector3d Normal /// /// Returns the actual length of this vector (RO). /// - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 Magnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -159,7 +159,7 @@ public Fixed64 Magnitude /// This is commonly used to determine the direction an object is facing in 3D space, /// where 'x' represents the yaw (horizontal rotation) and 'y' represents the pitch (vertical rotation). /// - [IgnoreMember] + [MemoryPackIgnore] public Vector3d Direction { get @@ -175,7 +175,7 @@ public Vector3d Direction /// Are all components of this vector equal to zero? /// /// - [IgnoreMember] + [MemoryPackIgnore] public bool IsZero { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -188,7 +188,7 @@ public bool IsZero /// If you need to know the actual distance, use MyMagnitude /// /// The magnitude. - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 SqrMagnitude { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -198,7 +198,7 @@ public Fixed64 SqrMagnitude /// /// Returns a long hash of the vector based on its x, y, and z values. /// - [IgnoreMember] + [MemoryPackIgnore] public long LongStateHash { [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -208,14 +208,14 @@ public long LongStateHash /// /// Returns a hash of the vector based on its state. /// - [IgnoreMember] + [MemoryPackIgnore] public int StateHash { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => (int)(LongStateHash % int.MaxValue); } - [IgnoreMember] + [MemoryPackIgnore] public Fixed64 this[int index] { [MethodImpl(MethodImplOptions.AggressiveInlining)] diff --git a/src/FixedMathSharp/Utility/DeterministicRandom.cs b/src/FixedMathSharp/Utility/DeterministicRandom.cs index 51e216b..d600d37 100644 --- a/src/FixedMathSharp/Utility/DeterministicRandom.cs +++ b/src/FixedMathSharp/Utility/DeterministicRandom.cs @@ -74,8 +74,8 @@ public int Next() [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Next(int maxExclusive) { - return maxExclusive <= 0 - ? throw new ArgumentOutOfRangeException(nameof(maxExclusive)) + return maxExclusive <= 0 + ? throw new ArgumentOutOfRangeException(nameof(maxExclusive)) : (int)NextBounded((uint)maxExclusive); } @@ -85,7 +85,7 @@ public int Next(int maxExclusive) [MethodImpl(MethodImplOptions.AggressiveInlining)] public int Next(int minInclusive, int maxExclusive) { - if (minInclusive >= maxExclusive) + if (minInclusive >= maxExclusive) throw new ArgumentException("min >= max"); uint range = (uint)(maxExclusive - minInclusive); return minInclusive + (int)NextBounded(range); diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs index b9f1452..3dd2d15 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests.Bounds @@ -186,18 +177,6 @@ public void BoundingArea_NetSerialization_RoundTripMaintainsData() new Vector3d(4, 5, 6) ); - // Serialize the BoundingArea object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (BoundingArea)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -207,7 +186,6 @@ public void BoundingArea_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -221,8 +199,8 @@ public void BoundingArea_MsgPackSerialization_RoundTripMaintainsData() new Vector3d(4, 5, 6) ); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - BoundingArea deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + BoundingArea deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs index a6a5179..6eddd79 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests.Bounds @@ -260,18 +251,6 @@ public void BoundingBox_NetSerialization_RoundTripMaintainsData() { BoundingBox originalValue = new(new Vector3d(0, 0, 0), new Vector3d(4, 4, 4)); - // Serialize the BoundingArea object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (BoundingBox)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -281,7 +260,6 @@ public void BoundingBox_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -292,8 +270,8 @@ public void BoundingBox_MsgPackSerialization_RoundTripMaintainsData() { BoundingBox originalValue = new(new Vector3d(0, 0, 0), new Vector3d(4, 4, 4)); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - BoundingBox deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + BoundingBox deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -304,8 +282,8 @@ public void MsgPack_SerializedBox_RemainsMutable() { var box = new BoundingBox(new Vector3d(0, 0, 0), new Vector3d(4, 4, 4)); - var bytes = MessagePackSerializer.Serialize(box); - var deserialized = MessagePackSerializer.Deserialize(bytes); + var bytes = MemoryPackSerializer.Serialize(box); + var deserialized = MemoryPackSerializer.Deserialize(bytes); deserialized.Resize(new Vector3d(2, 2, 2)); diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs index 9db6e78..5a72f6b 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests.Bounds @@ -197,18 +188,6 @@ public void BoundingSphere_NetSerialization_RoundTripMaintainsData() { BoundingSphere originalValue = new(new Vector3d(1, 1, 1), new Fixed64(2)); - // Serialize the BoundingArea object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (BoundingSphere)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -218,7 +197,6 @@ public void BoundingSphere_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -229,8 +207,8 @@ public void BoundingSphere_MsgPackSerialization_RoundTripMaintainsData() { BoundingSphere originalValue = new(new Vector3d(1, 1, 1), new Fixed64(2)); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - BoundingSphere deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + BoundingSphere deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/DeterministicRandom.Tests.cs b/tests/FixedMathSharp.Tests/DeterministicRandom.Tests.cs index 95d72ab..3e33dbc 100644 --- a/tests/FixedMathSharp.Tests/DeterministicRandom.Tests.cs +++ b/tests/FixedMathSharp.Tests/DeterministicRandom.Tests.cs @@ -1,7 +1,6 @@ -using System; +using FixedMathSharp.Utility; +using System; using System.Linq; -using System.Runtime.CompilerServices; -using FixedMathSharp.Utility; using Xunit; namespace FixedMathSharp.Tests diff --git a/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs b/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs index a64107d..6ad2061 100644 --- a/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests @@ -329,18 +320,6 @@ public void Fixed3x3_NetSerialization_RoundTripMaintainsData() { var original3x3 = Fixed3x3.CreateRotationX(FixedMath.PiOver2); // 90 degrees - // Serialize the Fixed3x3 object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, original3x3); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserialized3x3 = (Fixed3x3)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -350,7 +329,6 @@ public void Fixed3x3_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(original3x3, jsonOptions); var deserialized3x3 = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(original3x3, deserialized3x3); @@ -361,8 +339,8 @@ public void Fixed3x3_MsgPackSerialization_RoundTripMaintainsData() { Fixed3x3 originalValue = Fixed3x3.CreateRotationX(FixedMath.PiOver2); // 90 degrees - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - Fixed3x3 deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + Fixed3x3 deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs b/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs index 3fad24a..0e8841e 100644 --- a/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests @@ -326,19 +317,8 @@ public void Fixed4x4_NetSerialization_RoundTripMaintainsData() var original4x4 = Fixed4x4.ScaleRotateTranslate(translation, rotation, scale); - // Serialize the Fixed4x4 object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, original4x4); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserialized4x4 = (Fixed4x4)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER - var jsonOptions = new JsonSerializerOptions { + var jsonOptions = new JsonSerializerOptions + { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, ReferenceHandler = ReferenceHandler.IgnoreCycles, IncludeFields = true, @@ -346,7 +326,6 @@ public void Fixed4x4_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(original4x4, jsonOptions); var deserialized4x4 = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(original4x4, deserialized4x4); @@ -361,8 +340,8 @@ public void Fixed4x4_MsgPackSerialization_RoundTripMaintainsData() Fixed4x4 originalValue = Fixed4x4.ScaleRotateTranslate(translation, rotation, scale); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - Fixed4x4 deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + Fixed4x4 deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/Fixed64.Tests.cs b/tests/FixedMathSharp.Tests/Fixed64.Tests.cs index 3e8df2d..b4f6b7a 100644 --- a/tests/FixedMathSharp.Tests/Fixed64.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed64.Tests.cs @@ -1,16 +1,7 @@ -using MessagePack; +using MemoryPack; using System; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests @@ -124,7 +115,7 @@ public void Convert_ToDouble_ReturnsCorrectDouble() Assert.Equal(5.5, result); } -#endregion + #endregion #region Test: Fraction Method @@ -158,7 +149,7 @@ public void Subtract_OverflowProtection_ReturnsMinValue() } #endregion - + #region Test: Operations [Fact] @@ -205,18 +196,6 @@ public void Fixed64_NetSerialization_RoundTripMaintainsData() { var originalValue = FixedMath.PI; - // Serialize the Fixed64 object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (Fixed64)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -226,7 +205,6 @@ public void Fixed64_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -237,8 +215,8 @@ public void Fixed64_MsgPackSerialization_RoundTripMaintainsData() { Fixed64 originalValue = FixedMath.PI; - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - Fixed64 deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + Fixed64 deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/FixedCurveTests.cs b/tests/FixedMathSharp.Tests/FixedCurveTests.cs index 39c348e..3f9d1e0 100644 --- a/tests/FixedMathSharp.Tests/FixedCurveTests.cs +++ b/tests/FixedMathSharp.Tests/FixedCurveTests.cs @@ -1,16 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -using System.Security.Cryptography; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests @@ -142,18 +132,6 @@ public void FixedCurve_NetSerialization_RoundTripMaintainsData() new FixedCurveKey(0, 0), new FixedCurveKey(10, 100)); - // Serialize the Fixed3x3 object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalCurve); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedCurve = (FixedCurve)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -163,7 +141,6 @@ public void FixedCurve_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalCurve, jsonOptions); var deserializedCurve = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalCurve, deserializedCurve); @@ -177,8 +154,8 @@ public void FixedCurve_MsgPackSerialization_RoundTripMaintainsData() new FixedCurveKey(0, 0), new FixedCurveKey(10, 100)); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - FixedCurve deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + FixedCurve deserializedValue = MemoryPackSerializer.Deserialize(bytes)!; // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj index f1a2630..02b9ccc 100644 --- a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj +++ b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj @@ -15,24 +15,24 @@ compile; build all - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - all + + runtime; build; native; contentfiles; analyzers; buildtransitive + all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - runtime; build; native; contentfiles; analyzers; buildtransitive + + all + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs b/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs index 82732cf..2c2f2ff 100644 --- a/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs +++ b/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs @@ -1,15 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif - using Xunit; namespace FixedMathSharp.Tests @@ -156,7 +147,7 @@ public void FixedQuaternion_FromAxisAngle_WorksCorrectly() Assert.True(result.FuzzyEqual(expected), $"FromAxisAngle returned {result}, expected {expected}."); - axis = Vector3d.Forward; + axis = Vector3d.Forward; result = FixedQuaternion.FromAxisAngle(axis, angle); expected = new FixedQuaternion(Fixed64.Zero, Fixed64.Zero, FixedMath.Sin(FixedMath.PiOver4), FixedMath.Cos(FixedMath.PiOver4)); @@ -225,7 +216,7 @@ public void FixedQuaternion_ToAngularVelocity_ZeroForNoRotation() $"ToAngularVelocity should return zero for no rotation, but got {angularVelocity}"); } -#endregion + #endregion #region Test: Lerp and Slerp @@ -379,18 +370,6 @@ public void FixedQuanternion_NetSerialization_RoundTripMaintainsData() var originalRotation = quaternion.Rotated(sin, cos); - // Serialize the FixedQuaternion object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalRotation); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedRotation = (FixedQuaternion)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -400,7 +379,6 @@ public void FixedQuanternion_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalRotation, jsonOptions); var deserializedRotation = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalRotation, deserializedRotation); @@ -415,8 +393,8 @@ public void FixedQuanternion_MsgPackSerialization_RoundTripMaintainsData() FixedQuaternion originalValue = quaternion.Rotated(sin, cos); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - FixedQuaternion deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + FixedQuaternion deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/FixedRange.Tests.cs b/tests/FixedMathSharp.Tests/FixedRange.Tests.cs index 8c13f1b..aff4886 100644 --- a/tests/FixedMathSharp.Tests/FixedRange.Tests.cs +++ b/tests/FixedMathSharp.Tests/FixedRange.Tests.cs @@ -1,14 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif using Xunit; @@ -172,18 +164,6 @@ public void FixedRange_NetSerialization_RoundTripMaintainsData() { var originalRange = new FixedRange(new Fixed64(-10), new Fixed64(10)); - // Serialize the FixedRange object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalRange); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedRange = (FixedRange)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -193,7 +173,6 @@ public void FixedRange_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalRange, jsonOptions); var deserializedRange = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalRange.Min, deserializedRange.Min); @@ -205,8 +184,8 @@ public void FixedRange_MsgPackSerialization_RoundTripMaintainsData() { FixedRange originalValue = new FixedRange(new Fixed64(-10), new Fixed64(10)); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - FixedRange deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + FixedRange deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/Support/FixedMathTestHelper.cs b/tests/FixedMathSharp.Tests/Support/FixedMathTestHelper.cs index 953ccd1..89217f5 100644 --- a/tests/FixedMathSharp.Tests/Support/FixedMathTestHelper.cs +++ b/tests/FixedMathSharp.Tests/Support/FixedMathTestHelper.cs @@ -14,9 +14,9 @@ internal static class FixedMathTestHelper /// The relative tolerance to apply. /// Optional message for assertion failures. public static void AssertWithinRelativeTolerance( - Fixed64 expected, - Fixed64 actual, - Fixed64 tolerance = default, + Fixed64 expected, + Fixed64 actual, + Fixed64 tolerance = default, string message = "") { if (tolerance == default) @@ -42,9 +42,9 @@ public static void AssertWithinRelativeTolerance( /// An optional message to display if the assertion fails. /// public static void AssertWithinRange( - Fixed64 value, - Fixed64 min, - Fixed64 max, + Fixed64 value, + Fixed64 min, + Fixed64 max, string message = "") { Assert.True(value >= min && value <= max, diff --git a/tests/FixedMathSharp.Tests/Vector2d.Tests.cs b/tests/FixedMathSharp.Tests/Vector2d.Tests.cs index de21b3d..f6d24b2 100644 --- a/tests/FixedMathSharp.Tests/Vector2d.Tests.cs +++ b/tests/FixedMathSharp.Tests/Vector2d.Tests.cs @@ -1,14 +1,6 @@ -using MessagePack; - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif using Xunit; @@ -320,18 +312,6 @@ public void Vector2d_NetSerialization_RoundTripMaintainsData() { var originalValue = new Vector2d(FixedMath.PI, FixedMath.PiOver2); - // Serialize the Vector3d object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (Vector2d)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -341,7 +321,6 @@ public void Vector2d_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -352,8 +331,8 @@ public void Vector2d_MsgPackSerialization_RoundTripMaintainsData() { Vector2d originalValue = new Vector2d(FixedMath.PI, FixedMath.PiOver2); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - Vector2d deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + Vector2d deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); diff --git a/tests/FixedMathSharp.Tests/Vector3d.Tests.cs b/tests/FixedMathSharp.Tests/Vector3d.Tests.cs index 3c7e785..f2d1e64 100644 --- a/tests/FixedMathSharp.Tests/Vector3d.Tests.cs +++ b/tests/FixedMathSharp.Tests/Vector3d.Tests.cs @@ -1,16 +1,6 @@ -using MessagePack; -using System.Drawing; - - -#if NET48_OR_GREATER -using System.IO; -using System.Runtime.Serialization.Formatters.Binary; -#endif - -#if NET8_0_OR_GREATER +using MemoryPack; using System.Text.Json; using System.Text.Json.Serialization; -#endif using Xunit; @@ -239,7 +229,7 @@ public void Equality_TwoDifferentVectors_AreNotEqual() Assert.True(v1 != v2); } -#endregion + #endregion #region Test: Static Math @@ -593,24 +583,11 @@ public void V3InverseRotateVector_AppliesInverseRotationCorrectly_WithFuzzyEqual #region Test: Serialization - [Fact] public void Vector3d_NetSerialization_RoundTripMaintainsData() { var originalValue = new Vector3d(FixedMath.PI, FixedMath.PiOver2, FixedMath.TwoPI); - // Serialize the Vector3d object -#if NET48_OR_GREATER - var formatter = new BinaryFormatter(); - using var stream = new MemoryStream(); - formatter.Serialize(stream, originalValue); - - // Reset stream position and deserialize - stream.Seek(0, SeekOrigin.Begin); - var deserializedValue = (Vector3d)formatter.Deserialize(stream); -#endif - -#if NET8_0_OR_GREATER var jsonOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, @@ -620,7 +597,6 @@ public void Vector3d_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalValue, jsonOptions); var deserializedValue = JsonSerializer.Deserialize(json, jsonOptions); -#endif // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); @@ -631,8 +607,8 @@ public void Vector3d_MsgPackSerialization_RoundTripMaintainsData() { Vector3d originalValue = new Vector3d(FixedMath.PI, FixedMath.PiOver2, FixedMath.TwoPI); - byte[] bytes = MessagePackSerializer.Serialize(originalValue); - Vector3d deserializedValue = MessagePackSerializer.Deserialize(bytes); + byte[] bytes = MemoryPackSerializer.Serialize(originalValue); + Vector3d deserializedValue = MemoryPackSerializer.Deserialize(bytes); // Check that deserialized values match the original Assert.Equal(originalValue, deserializedValue); From 638e983f926a35c492db09b526d723fcd83e479c Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 13:07:19 -0500 Subject: [PATCH 3/8] task: update README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7916bf4..6452853 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Ideal for simulations, games, and physics engines requiring reliable arithmetic - **Bounding Shapes:** Includes `IBound` structs `BoundingBox`, `BoundingSphere`, and `BoundingArea` for lightweight spatial calculations. - **Advanced Math Functions:** Includes trigonometry and common math utilities. - **Framework Agnostic:** Works with **.NET, Unity, and other game engines**. -- **Full Serialization Support:** Out-of-the-box round-trip serialization via BinaryFormatter (for .NET Framework 4.8+), System.Text.Json (for .NET 8+), and MessagePack across all serializable structs. +- **Full Serialization Support:** Out-of-the-box round-trip serialization via `MemoryPack` across all serializable structs, with `System.Text.Json` constructor support on .NET 8+. --- @@ -176,8 +176,8 @@ dotnet test --configuration debug ## 🛠️ Compatibility -- **.NET Framework** 4.7.2+ -- **.NET Core / .NET** 6+ +- **.NET Standard** 2.1 +- **.NET** 8 - **Unity 2020+** (via [FixedMathSharp-Unity](https://github.com/mrdav30/FixedMathSharp-Unity)) - **Cross-Platform Support** (Windows, Linux, macOS) From 794ce1bf38d2318137e2431affabbb73164b3d98 Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 22:57:59 -0500 Subject: [PATCH 4/8] refactor: git actions wo net48 --- .github/workflows/dotnet.yml | 104 ++++++----------------------------- 1 file changed, 18 insertions(+), 86 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 91564f4..aea8771 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -1,45 +1,36 @@ -# This workflow builds and tests the FixedMathSharp .NET project. -# Documentation: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-net - name: .NET CI on: - # Run the workflow on all branch pushes and pull requests push: branches-ignore: - - 'dependabot/**' #avoid duplicates: only run the PR, not the push - - 'gh-pages' #github pages do not trigger all tests + - 'dependabot/**' + - 'gh-pages' tags-ignore: - - 'v*' #avoid rerun existing commit on release + - 'v*' pull_request: branches: - 'main' jobs: - build-and-test-linux: - if: | - (github.event_name != 'pull_request' && !github.event.pull_request.head.repo.fork) - || (github.event_name == 'pull_request' && (github.event.pull_request.head.repo.fork - || startsWith(github.head_ref, 'dependabot/'))) - runs-on: ubuntu-latest + build-and-test: + runs-on: ${{ matrix.os }} + + strategy: + matrix: + os: [ubuntu-latest, windows-latest] steps: - name: Checkout repository uses: actions/checkout@v4 with: fetch-depth: 0 - persist-credentials: false # Ensure credentials aren't retained + persist-credentials: false - name: Setup .NET uses: actions/setup-dotnet@v4 with: dotnet-version: 8.0.x - - - name: Install Mono (required for .NET Framework tests on Linux) - run: | - sudo apt update - sudo apt install -y mono-complete - + - name: Install GitVersion uses: gittools/actions/gitversion/setup@v3.1.1 with: @@ -54,12 +45,13 @@ jobs: ${{ runner.os }}-nuget- - name: Determine Version - id: version_step + shell: bash run: | - chown -R $(whoami) $(pwd) dotnet-gitversion /output json > version.json - echo "FULL_SEM_VER=$(grep -oP '"FullSemVer":\s*"\K[^"]+' version.json)" >> $GITHUB_ENV - echo "ASSEMBLY_VERSION=$(grep -oP '"AssemblySemFileVer":\s*"\K[^"]+' version.json)" >> $GITHUB_ENV + FULL_SEM_VER=$(jq -r .FullSemVer version.json) + ASSEMBLY_VERSION=$(jq -r .AssemblySemFileVer version.json) + echo "FULL_SEM_VER=$FULL_SEM_VER" >> $GITHUB_ENV + echo "ASSEMBLY_VERSION=$ASSEMBLY_VERSION" >> $GITHUB_ENV - name: Restore dependencies run: dotnet restore @@ -70,65 +62,5 @@ jobs: echo "Assembly Version: ${{ env.ASSEMBLY_VERSION }}" dotnet build --configuration Debug --no-restore - - name: Test .NET48 - run: | - mono ~/.nuget/packages/xunit.runner.console/2.9.3/tools/net48/xunit.console.exe ${{github.workspace}}/tests/FixedMathSharp.Tests/bin/Debug/net48/FixedMathSharp.Tests.dll - - - name: Test .NET8 - run: | - dotnet test -f net8 --verbosity normal - - build-and-test-windows: - if: | - (github.event_name != 'pull_request' && !github.event.pull_request.head.repo.fork) - || (github.event_name == 'pull_request' && (github.event.pull_request.head.repo.fork - || startsWith(github.head_ref, 'dependabot/'))) - runs-on: windows-latest - steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - fetch-depth: 0 - persist-credentials: false - - - name: Setup .NET - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.x - - - name: Install GitVersion - uses: gittools/actions/gitversion/setup@v3.1.1 - with: - versionSpec: 6.0.x - - - name: Cache NuGet packages - uses: actions/cache@v3 - with: - path: ~/.nuget/packages - key: '${{ runner.os }}-nuget-${{ hashFiles(''**/*.csproj'', ''**/*.sln'') }}' - restore-keys: | - ${{ runner.os }}-nuget- - - - name: Determine Version - id: version_step - shell: pwsh - run: | - chown -R $env:USERNAME $(Get-Location) - dotnet-gitversion /output json | Out-File -FilePath version.json - $json = Get-Content version.json | ConvertFrom-Json - echo "FULL_SEM_VER=$($json.FullSemVer)" | Out-File -FilePath $env:GITHUB_ENV -Append - echo "ASSEMBLY_VERSION=$($json.AssemblySemFileVer)" | Out-File -FilePath $env:GITHUB_ENV -Append - - - name: Restore dependencies - run: dotnet restore - - - name: Build Solution - run: | - echo "Version: ${{ env.FULL_SEM_VER }}" - echo "Assembly Version: ${{ env.ASSEMBLY_VERSION }}" - dotnet build --configuration Debug --no-restore - - - name: Test .NET48 & .NET8 - run: | - dotnet --info - dotnet test --verbosity normal + - name: Run Tests (net8.0) + run: dotnet test --configuration Debug --no-build --verbosity normal \ No newline at end of file From a6aa5801b1210fcde5755ca9f9dc926bb6c3803a Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 23:15:04 -0500 Subject: [PATCH 5/8] fix: action runner --- .github/workflows/dotnet.yml | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index aea8771..5031bf7 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -13,6 +13,10 @@ on: jobs: build-and-test: + if: | + (github.event_name != 'pull_request' && !github.event.pull_request.head.repo.fork) + || (github.event_name == 'pull_request' && (github.event.pull_request.head.repo.fork + || startsWith(github.head_ref, 'dependabot/'))) runs-on: ${{ matrix.os }} strategy: @@ -31,11 +35,15 @@ jobs: with: dotnet-version: 8.0.x - - name: Install GitVersion + - name: Setup GitVersion uses: gittools/actions/gitversion/setup@v3.1.1 with: versionSpec: '6.0.x' + - name: Execute GitVersion + id: gitversion + uses: gittools/actions/gitversion/execute@v3.1.1 + - name: Cache NuGet packages uses: actions/cache@v3 with: @@ -44,23 +52,14 @@ jobs: restore-keys: | ${{ runner.os }}-nuget- - - name: Determine Version - shell: bash - run: | - dotnet-gitversion /output json > version.json - FULL_SEM_VER=$(jq -r .FullSemVer version.json) - ASSEMBLY_VERSION=$(jq -r .AssemblySemFileVer version.json) - echo "FULL_SEM_VER=$FULL_SEM_VER" >> $GITHUB_ENV - echo "ASSEMBLY_VERSION=$ASSEMBLY_VERSION" >> $GITHUB_ENV - - name: Restore dependencies run: dotnet restore - name: Build Solution run: | - echo "Version: ${{ env.FULL_SEM_VER }}" - echo "Assembly Version: ${{ env.ASSEMBLY_VERSION }}" + echo "Version: ${{ steps.gitversion.outputs.fullSemVer }}" + echo "Assembly Version: ${{ steps.gitversion.outputs.assemblySemFileVer }}" dotnet build --configuration Debug --no-restore - - name: Run Tests (net8.0) + - name: Run Tests run: dotnet test --configuration Debug --no-build --verbosity normal \ No newline at end of file From 600e379a201d7fdbf135ab55ebb14a11cc9a5c95 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Tue, 3 Mar 2026 23:38:54 -0500 Subject: [PATCH 6/8] Fix TFMs, exception args, stray semicolons, XML doc, and AGENTS.md from review feedback (#45) * fix: apply PR review feedback - TFMs, exception args, stray semicolons, XML doc, AGENTS.md Co-authored-by: mrdav30 <11547347+mrdav30@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mrdav30 <11547347+mrdav30@users.noreply.github.com> --- AGENTS.md | 12 ++++++------ src/FixedMathSharp/Bounds/BoundingArea.cs | 1 - src/FixedMathSharp/Bounds/BoundingBox.cs | 3 +-- src/FixedMathSharp/Bounds/BoundingSphere.cs | 1 - src/FixedMathSharp/FixedMathSharp.csproj | 6 +----- src/FixedMathSharp/Numerics/FixedQuaternion.cs | 4 ++-- .../FixedMathSharp.Tests/FixedMathSharp.Tests.csproj | 6 +----- 7 files changed, 11 insertions(+), 22 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 60ed110..4eae149 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,23 +8,23 @@ ## Build and test workflows - Solution: `FixedMathSharp.sln` with library project and test project. -- Target frameworks are multi-targeted in both projects: `net48;net8`. +- Target frameworks are configured in the respective `.csproj` files; `net8.0` is the primary TFM. - Typical local workflow: - `dotnet restore` - `dotnet build --configuration Debug --no-restore` - `dotnet test --configuration Debug` - CI detail from `.github/workflows/dotnet.yml`: - - Linux runs `net48` tests via Mono + `xunit.console.exe` and `net8` via `dotnet test -f net8`. - - Windows runs `dotnet test` for both TFMs. + - Linux and Windows both run `dotnet test` against the supported TFMs (with `net8.0` as the primary test target). + - Refer to the workflow file for the exact matrix of OS/TFM combinations. - Packaging/versioning comes from `src/FixedMathSharp/FixedMathSharp.csproj`: GitVersion variables are consumed when present, otherwise version falls back to `0.0.0`. ## Code conventions specific to this repo - Prefer `Fixed64` constants (`Fixed64.Zero`, `Fixed64.One`, `FixedMath.PI`) over primitive literals in math-heavy code. - Preserve saturating/guarded semantics in operators and math helpers (for example `Fixed64` add/sub overflow behavior). - When touching bounds logic, maintain cross-type dispatch shape in `Intersects(IBound)` and shared clamping projection via `IBoundExtensions.ProjectPointWithinBounds`. -- Serialization compatibility is intentional: - - MessagePack attributes on serializable structs (`[MessagePackObject]`, `[Key]`) across TFMs. - - Conditional serializers in tests (`BinaryFormatter` for `NET48`, `System.Text.Json` for `NET8`). +- Serialization compatibility is intentional and now uses MemoryPack: + - MemoryPack attributes on serializable structs (for example `[MemoryPackable]`, `[MemoryPackInclude]`) are the source of truth for serialized layouts. + - Tests use MemoryPack-based roundtrips (and `System.Text.Json` where appropriate) instead of legacy `MessagePack`/`BinaryFormatter` serializers. - `ThreadLocalRandom` is marked `[Obsolete]`; new deterministic RNG work should prefer `DeterministicRandom` and `DeterministicRandom.FromWorldFeature(...)` in `src/FixedMathSharp/Utility/DeterministicRandom.cs`. ## Testing patterns to mirror diff --git a/src/FixedMathSharp/Bounds/BoundingArea.cs b/src/FixedMathSharp/Bounds/BoundingArea.cs index b526ec3..e5bc39e 100644 --- a/src/FixedMathSharp/Bounds/BoundingArea.cs +++ b/src/FixedMathSharp/Bounds/BoundingArea.cs @@ -209,7 +209,6 @@ public bool Intersects(IBound other) default: return false; // Default case for unknown or unsupported types } - ; } /// diff --git a/src/FixedMathSharp/Bounds/BoundingBox.cs b/src/FixedMathSharp/Bounds/BoundingBox.cs index d93c666..b32b7ca 100644 --- a/src/FixedMathSharp/Bounds/BoundingBox.cs +++ b/src/FixedMathSharp/Bounds/BoundingBox.cs @@ -39,7 +39,7 @@ public partial struct BoundingBox : IBound, IEquatable public Vector3d Max { get; private set; } /// - /// + /// Serialization/compatibility version of this instance. /// [MemoryPackOrder(2)] public byte Version { get; private set; } @@ -238,7 +238,6 @@ public bool Intersects(IBound other) default: return false; // Default case for unknown or unsupported types } - ; } /// diff --git a/src/FixedMathSharp/Bounds/BoundingSphere.cs b/src/FixedMathSharp/Bounds/BoundingSphere.cs index df13653..42c2665 100644 --- a/src/FixedMathSharp/Bounds/BoundingSphere.cs +++ b/src/FixedMathSharp/Bounds/BoundingSphere.cs @@ -108,7 +108,6 @@ public bool Intersects(IBound other) default: return false; // Default case for unknown or unsupported types } - ; } /// diff --git a/src/FixedMathSharp/FixedMathSharp.csproj b/src/FixedMathSharp/FixedMathSharp.csproj index 56b864f..9da0600 100644 --- a/src/FixedMathSharp/FixedMathSharp.csproj +++ b/src/FixedMathSharp/FixedMathSharp.csproj @@ -3,7 +3,7 @@ 11.0 - netstandard2.1;net8 + netstandard2.1;net8.0 $(GitVersion_FullSemVer) @@ -68,10 +68,6 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/src/FixedMathSharp/Numerics/FixedQuaternion.cs b/src/FixedMathSharp/Numerics/FixedQuaternion.cs index 3618472..8700d9f 100644 --- a/src/FixedMathSharp/Numerics/FixedQuaternion.cs +++ b/src/FixedMathSharp/Numerics/FixedQuaternion.cs @@ -372,7 +372,7 @@ public static FixedQuaternion FromAxisAngle(Vector3d axis, Fixed64 angle) // Check if the angle is in a valid range (-pi, pi) if (angle < -FixedMath.PI || angle > FixedMath.PI) - throw new ArgumentOutOfRangeException($"Angle must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {angle}"); + throw new ArgumentOutOfRangeException(nameof(angle), angle, $"Angle must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {angle}"); Fixed64 halfAngle = angle / Fixed64.Two; // Half-angle formula Fixed64 sinHalfAngle = FixedMath.Sin(halfAngle); @@ -412,7 +412,7 @@ public static FixedQuaternion FromEulerAngles(Fixed64 pitch, Fixed64 yaw, Fixed6 yaw < -FixedMath.PI || yaw > FixedMath.PI || roll < -FixedMath.PI || roll > FixedMath.PI) { - throw new ArgumentOutOfRangeException($"Euler angles must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but were ({pitch}, {yaw}, {roll})"); + throw new ArgumentOutOfRangeException(nameof(pitch), $"Euler angles must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but were ({pitch}, {yaw}, {roll})"); } Fixed64 c1 = FixedMath.Cos(yaw / Fixed64.Two); diff --git a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj index 02b9ccc..eb32999 100644 --- a/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj +++ b/tests/FixedMathSharp.Tests/FixedMathSharp.Tests.csproj @@ -1,7 +1,7 @@  11.0 - net8 + net8.0 disable enable false @@ -16,10 +16,6 @@ all - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - runtime; build; native; contentfiles; analyzers; buildtransitive From 329a113c3a9200c18639145a13515043806f77bb Mon Sep 17 00:00:00 2001 From: "DESKTOP-5KM6RA3\\david" Date: Tue, 3 Mar 2026 23:44:36 -0500 Subject: [PATCH 7/8] update: drop ThreadLocalRandom support --- .../Utility/ThreadLocalRandom.cs | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 src/FixedMathSharp/Utility/ThreadLocalRandom.cs diff --git a/src/FixedMathSharp/Utility/ThreadLocalRandom.cs b/src/FixedMathSharp/Utility/ThreadLocalRandom.cs deleted file mode 100644 index 393da6c..0000000 --- a/src/FixedMathSharp/Utility/ThreadLocalRandom.cs +++ /dev/null @@ -1,71 +0,0 @@ -using System; -using System.Threading; - -namespace FixedMathSharp.Utility -{ - /// - /// Deterministic per-thread RNG facade. - /// - [Obsolete("ThreadLocalRandom is deprecated. Use DeterministicRandom or DeterministicRandom.FromWorldFeature(...) for deterministic streams.", false)] - public static class ThreadLocalRandom - { - private static ulong _rootSeed = 0; - private static Func _threadIndexProvider = null!; - private static ThreadLocal _threadRng = null!; - - /// - /// Initialize global deterministic seeding. - /// Provide a stable threadIndex (0..T-1) for each thread. - /// - public static void Initialize(ulong rootSeed, Func threadIndexProvider) - { - _rootSeed = rootSeed; - _threadIndexProvider = threadIndexProvider ?? throw new ArgumentNullException(nameof(threadIndexProvider)); - - _threadRng = new ThreadLocal(() => - { - int idx = _threadIndexProvider(); - // Derive a unique stream per thread deterministically from rootSeed + idx. - return DeterministicRandom.FromWorldFeature(_rootSeed, (ulong)idx); - }); - } - - /// - /// Create a new independent RNG from a specific seed (does not affect thread Instance). - /// - public static DeterministicRandom NewRandom(ulong seed) => new(seed); - - /// - /// Per-thread RNG instance (requires Initialize to be called first). - /// - public static DeterministicRandom Instance - { - get - { - if (_threadRng == null) - throw new InvalidOperationException("ThreadLocalRandom.Initialize(rootSeed, threadIndexProvider) must be called first."); - return _threadRng.Value; - } - } - - #region Convenience mirrors - - public static int Next() => Instance.Next(); - public static int Next(int maxExclusive) => Instance.Next(maxExclusive); - public static int Next(int minInclusive, int maxExclusive) => Instance.Next(minInclusive, maxExclusive); - public static double NextDouble() => Instance.NextDouble(); - public static double NextDouble(double min, double max) => Instance.NextDouble() * (max - min) + min; - - public static void NextBytes(byte[] buffer) - { - if (buffer == null) throw new ArgumentNullException(nameof(buffer)); - Instance.NextBytes(buffer); - } - - public static Fixed64 NextFixed6401() => Instance.NextFixed6401(); - public static Fixed64 NextFixed64(Fixed64 maxExclusive) => Instance.NextFixed64(maxExclusive); - public static Fixed64 NextFixed64(Fixed64 minInclusive, Fixed64 maxExclusive) => Instance.NextFixed64(minInclusive, maxExclusive); - - #endregion - } -} From 9bcb1c64efbd902b21aacd97244436a96112dbf3 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 4 Mar 2026 00:39:25 -0500 Subject: [PATCH 8/8] Fix review feedback: MemoryPack test names, BoundingBox.Union version, CI internal PRs, nullable deserialization, per-arg quaternion exceptions (#46) * Initial plan * Apply review feedback: rename MsgPack tests, fix Union Version, CI workflow, null check, separate exceptions Co-authored-by: mrdav30 <11547347+mrdav30@users.noreply.github.com> * Update src/FixedMathSharp/Bounds/BoundingBox.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mrdav30 <11547347+mrdav30@users.noreply.github.com> Co-authored-by: mrdav30 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/dotnet.yml | 4 ---- src/FixedMathSharp/Bounds/BoundingBox.cs | 1 + src/FixedMathSharp/Numerics/FixedQuaternion.cs | 12 ++++++------ .../Bounds/BoundingArea.Tests.cs | 2 +- .../FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs | 4 ++-- .../Bounds/BoundingSphere.Tests.cs | 2 +- tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs | 2 +- tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs | 2 +- tests/FixedMathSharp.Tests/Fixed64.Tests.cs | 2 +- tests/FixedMathSharp.Tests/FixedCurveTests.cs | 3 ++- tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs | 2 +- tests/FixedMathSharp.Tests/FixedRange.Tests.cs | 2 +- tests/FixedMathSharp.Tests/Vector2d.Tests.cs | 2 +- tests/FixedMathSharp.Tests/Vector3d.Tests.cs | 2 +- 14 files changed, 20 insertions(+), 22 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 5031bf7..76f665a 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -13,10 +13,6 @@ on: jobs: build-and-test: - if: | - (github.event_name != 'pull_request' && !github.event.pull_request.head.repo.fork) - || (github.event_name == 'pull_request' && (github.event.pull_request.head.repo.fork - || startsWith(github.head_ref, 'dependabot/'))) runs-on: ${{ matrix.os }} strategy: diff --git a/src/FixedMathSharp/Bounds/BoundingBox.cs b/src/FixedMathSharp/Bounds/BoundingBox.cs index b32b7ca..8dcd271 100644 --- a/src/FixedMathSharp/Bounds/BoundingBox.cs +++ b/src/FixedMathSharp/Bounds/BoundingBox.cs @@ -392,6 +392,7 @@ public static BoundingBox Union(BoundingBox a, BoundingBox b) { Min = Vector3d.Min(a.Min, b.Min), Max = Vector3d.Max(a.Max, b.Max), + Version = (byte)Math.Max(a.Version, b.Version), _isDirty = true }; } diff --git a/src/FixedMathSharp/Numerics/FixedQuaternion.cs b/src/FixedMathSharp/Numerics/FixedQuaternion.cs index 8700d9f..a0ab54e 100644 --- a/src/FixedMathSharp/Numerics/FixedQuaternion.cs +++ b/src/FixedMathSharp/Numerics/FixedQuaternion.cs @@ -408,12 +408,12 @@ public static FixedQuaternion FromEulerAnglesInDegrees(Fixed64 pitch, Fixed64 ya public static FixedQuaternion FromEulerAngles(Fixed64 pitch, Fixed64 yaw, Fixed64 roll) { // Check if the angles are in a valid range (-pi, pi) - if (pitch < -FixedMath.PI || pitch > FixedMath.PI || - yaw < -FixedMath.PI || yaw > FixedMath.PI || - roll < -FixedMath.PI || roll > FixedMath.PI) - { - throw new ArgumentOutOfRangeException(nameof(pitch), $"Euler angles must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but were ({pitch}, {yaw}, {roll})"); - } + if (pitch < -FixedMath.PI || pitch > FixedMath.PI) + throw new ArgumentOutOfRangeException(nameof(pitch), pitch, $"Pitch must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {pitch}"); + if (yaw < -FixedMath.PI || yaw > FixedMath.PI) + throw new ArgumentOutOfRangeException(nameof(yaw), yaw, $"Yaw must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {yaw}"); + if (roll < -FixedMath.PI || roll > FixedMath.PI) + throw new ArgumentOutOfRangeException(nameof(roll), roll, $"Roll must be in the range ({-FixedMath.PI}, {FixedMath.PI}), but was {roll}"); Fixed64 c1 = FixedMath.Cos(yaw / Fixed64.Two); Fixed64 s1 = FixedMath.Sin(yaw / Fixed64.Two); diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs index 3dd2d15..c9e6a6d 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingArea.Tests.cs @@ -192,7 +192,7 @@ public void BoundingArea_NetSerialization_RoundTripMaintainsData() } [Fact] - public void BoundingArea_MsgPackSerialization_RoundTripMaintainsData() + public void BoundingArea_MemoryPackSerialization_RoundTripMaintainsData() { BoundingArea originalValue = new( new Vector3d(1, 2, 3), diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs index 6eddd79..16c02c2 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingBox.Tests.cs @@ -266,7 +266,7 @@ public void BoundingBox_NetSerialization_RoundTripMaintainsData() } [Fact] - public void BoundingBox_MsgPackSerialization_RoundTripMaintainsData() + public void BoundingBox_MemoryPackSerialization_RoundTripMaintainsData() { BoundingBox originalValue = new(new Vector3d(0, 0, 0), new Vector3d(4, 4, 4)); @@ -278,7 +278,7 @@ public void BoundingBox_MsgPackSerialization_RoundTripMaintainsData() } [Fact] - public void MsgPack_SerializedBox_RemainsMutable() + public void MemoryPack_SerializedBox_RemainsMutable() { var box = new BoundingBox(new Vector3d(0, 0, 0), new Vector3d(4, 4, 4)); diff --git a/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs b/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs index 5a72f6b..3d7a02f 100644 --- a/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs +++ b/tests/FixedMathSharp.Tests/Bounds/BoundingSphere.Tests.cs @@ -203,7 +203,7 @@ public void BoundingSphere_NetSerialization_RoundTripMaintainsData() } [Fact] - public void BoundingSphere_MsgPackSerialization_RoundTripMaintainsData() + public void BoundingSphere_MemoryPackSerialization_RoundTripMaintainsData() { BoundingSphere originalValue = new(new Vector3d(1, 1, 1), new Fixed64(2)); diff --git a/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs b/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs index 6ad2061..9c2438b 100644 --- a/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed3x3.Tests.cs @@ -335,7 +335,7 @@ public void Fixed3x3_NetSerialization_RoundTripMaintainsData() } [Fact] - public void Fixed3x3_MsgPackSerialization_RoundTripMaintainsData() + public void Fixed3x3_MemoryPackSerialization_RoundTripMaintainsData() { Fixed3x3 originalValue = Fixed3x3.CreateRotationX(FixedMath.PiOver2); // 90 degrees diff --git a/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs b/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs index 0e8841e..318ed68 100644 --- a/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed4x4.Tests.cs @@ -332,7 +332,7 @@ public void Fixed4x4_NetSerialization_RoundTripMaintainsData() } [Fact] - public void Fixed4x4_MsgPackSerialization_RoundTripMaintainsData() + public void Fixed4x4_MemoryPackSerialization_RoundTripMaintainsData() { var translation = new Vector3d(1, 2, 3); var rotation = FixedQuaternion.FromEulerAnglesInDegrees(Fixed64.Zero, FixedMath.PiOver2, Fixed64.Zero); diff --git a/tests/FixedMathSharp.Tests/Fixed64.Tests.cs b/tests/FixedMathSharp.Tests/Fixed64.Tests.cs index b4f6b7a..7a273b8 100644 --- a/tests/FixedMathSharp.Tests/Fixed64.Tests.cs +++ b/tests/FixedMathSharp.Tests/Fixed64.Tests.cs @@ -211,7 +211,7 @@ public void Fixed64_NetSerialization_RoundTripMaintainsData() } [Fact] - public void Fixed64_MsgPackSerialization_RoundTripMaintainsData() + public void Fixed64_MemoryPackSerialization_RoundTripMaintainsData() { Fixed64 originalValue = FixedMath.PI; diff --git a/tests/FixedMathSharp.Tests/FixedCurveTests.cs b/tests/FixedMathSharp.Tests/FixedCurveTests.cs index 3f9d1e0..f329f1c 100644 --- a/tests/FixedMathSharp.Tests/FixedCurveTests.cs +++ b/tests/FixedMathSharp.Tests/FixedCurveTests.cs @@ -141,13 +141,14 @@ public void FixedCurve_NetSerialization_RoundTripMaintainsData() }; var json = JsonSerializer.SerializeToUtf8Bytes(originalCurve, jsonOptions); var deserializedCurve = JsonSerializer.Deserialize(json, jsonOptions); + Assert.NotNull(deserializedCurve); // Check that deserialized values match the original Assert.Equal(originalCurve, deserializedCurve); } [Fact] - public void FixedCurve_MsgPackSerialization_RoundTripMaintainsData() + public void FixedCurve_MemoryPackSerialization_RoundTripMaintainsData() { FixedCurve originalValue = new FixedCurve( new FixedCurveKey(-10, -100), diff --git a/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs b/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs index 2c2f2ff..4ff96a8 100644 --- a/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs +++ b/tests/FixedMathSharp.Tests/FixedQuanternion.Tests.cs @@ -385,7 +385,7 @@ public void FixedQuanternion_NetSerialization_RoundTripMaintainsData() } [Fact] - public void FixedQuanternion_MsgPackSerialization_RoundTripMaintainsData() + public void FixedQuanternion_MemoryPackSerialization_RoundTripMaintainsData() { var quaternion = FixedQuaternion.Identity; var sin = FixedMath.Sin(FixedMath.PiOver4); // 45° rotation diff --git a/tests/FixedMathSharp.Tests/FixedRange.Tests.cs b/tests/FixedMathSharp.Tests/FixedRange.Tests.cs index aff4886..253f317 100644 --- a/tests/FixedMathSharp.Tests/FixedRange.Tests.cs +++ b/tests/FixedMathSharp.Tests/FixedRange.Tests.cs @@ -180,7 +180,7 @@ public void FixedRange_NetSerialization_RoundTripMaintainsData() } [Fact] - public void FixedRange_MsgPackSerialization_RoundTripMaintainsData() + public void FixedRange_MemoryPackSerialization_RoundTripMaintainsData() { FixedRange originalValue = new FixedRange(new Fixed64(-10), new Fixed64(10)); diff --git a/tests/FixedMathSharp.Tests/Vector2d.Tests.cs b/tests/FixedMathSharp.Tests/Vector2d.Tests.cs index f6d24b2..8c36d64 100644 --- a/tests/FixedMathSharp.Tests/Vector2d.Tests.cs +++ b/tests/FixedMathSharp.Tests/Vector2d.Tests.cs @@ -327,7 +327,7 @@ public void Vector2d_NetSerialization_RoundTripMaintainsData() } [Fact] - public void Vector2d_MsgPackSerialization_RoundTripMaintainsData() + public void Vector2d_MemoryPackSerialization_RoundTripMaintainsData() { Vector2d originalValue = new Vector2d(FixedMath.PI, FixedMath.PiOver2); diff --git a/tests/FixedMathSharp.Tests/Vector3d.Tests.cs b/tests/FixedMathSharp.Tests/Vector3d.Tests.cs index f2d1e64..d60d6e4 100644 --- a/tests/FixedMathSharp.Tests/Vector3d.Tests.cs +++ b/tests/FixedMathSharp.Tests/Vector3d.Tests.cs @@ -603,7 +603,7 @@ public void Vector3d_NetSerialization_RoundTripMaintainsData() } [Fact] - public void Vector3d_MsgPackSerialization_RoundTripMaintainsData() + public void Vector3d_MemoryPackSerialization_RoundTripMaintainsData() { Vector3d originalValue = new Vector3d(FixedMath.PI, FixedMath.PiOver2, FixedMath.TwoPI);