|
9 | 9 | [](https://github.com/mrdav30/FixedMathSharp/blob/main/LICENSE) |
10 | 10 | [](https://github.com/mrdav30/FixedMathSharp) |
11 | 11 |
|
12 | | -**A deterministic fixed-point math library for .NET.** |
13 | | -Built for simulations, games, and physics-heavy code that needs reliable results without floating-point drift. |
| 12 | +**Deterministic fixed-point math for .NET simulations, games, tools, and procedural systems.** |
14 | 13 |
|
15 | | ---- |
16 | | - |
17 | | -## 🛠️ Key Features |
18 | | - |
19 | | -- **Deterministic fixed-point arithmetic:** Consistent results across platforms with `Fixed64`. |
20 | | -- **Core math types included:** `Vector2d`, `Vector3d`, `FixedQuaternion`, `Fixed3x3`, and `Fixed4x4`. |
21 | | -- **Spatial helpers:** `BoundingBox`, `BoundingSphere`, and `BoundingArea` for lightweight bounds checks. |
22 | | -- **Shared math utilities:** Common math and trigonometry helpers via `FixedMath` and `FixedTrigonometry`. |
23 | | -- **Deterministic RNG:** `DeterministicRandom` for repeatable procedural generation and simulations. |
24 | | -- **Flexible packaging:** Use the default package with `MemoryPack`, or the `Lean` package when you want the same API without that dependency. |
25 | | -- **Broad .NET compatibility:** Targets modern .NET while remaining friendly to engine and tooling workflows. |
| 14 | +FixedMathSharp gives you a practical Q32.32 fixed-point numeric stack: scalar math, vectors, matrices, quaternions, bounds, curves, and deterministic random generation. It is built for code where the same inputs should produce the same results across machines, runs, replays, and networked clients. |
26 | 15 |
|
27 | 16 | --- |
28 | 17 |
|
29 | | -## 🚀 Installation |
| 18 | +## Why Fixed-Point? |
30 | 19 |
|
31 | | -For most .NET projects, start with the standard package: |
| 20 | +Floating-point math is fast, hardware-accelerated, and the right choice for rendering, visual effects, and many everyday calculations. It is also allowed to vary in small ways across runtimes, processors, compiler settings, instruction sets, and evaluation order. |
32 | 21 |
|
33 | | -```bash |
34 | | -dotnet add package FixedMathSharp |
35 | | -``` |
| 22 | +Fixed-point math stores numbers as scaled integers. In FixedMathSharp, `Fixed64` uses a Q32.32 layout: 32 bits for the whole-number side and 32 bits for the fractional side. That trade gives you deterministic arithmetic with predictable rounding behavior, at the cost of less dynamic range than `double` and less raw throughput than native floating point. |
36 | 23 |
|
37 | | -### Non-Unity Projects |
| 24 | +Use FixedMathSharp when you need: |
38 | 25 |
|
39 | | -Choose the package that fits your runtime: |
| 26 | +- Lockstep multiplayer, replay systems, rollback, or deterministic simulation. |
| 27 | +- Procedural generation that must be reproducible from the same seed. |
| 28 | +- Gameplay, physics-adjacent, or tooling logic where drift and platform differences are painful. |
| 29 | +- Serializable math values with stable behavior across .NET targets. |
40 | 30 |
|
41 | | -| Package | Best for | Install | |
42 | | -| --- | --- | --- | |
43 | | -| `FixedMathSharp` | Most .NET applications. Includes built-in `MemoryPack` support. | `dotnet add package FixedMathSharp` | |
44 | | -| `FixedMathSharp.Lean` | Projects that want the same math API without a `MemoryPack` dependency, including custom serializer setups and Burst AOT-sensitive workflows. | `dotnet add package FixedMathSharp.Lean` | |
| 31 | +Use floating point when you need: |
45 | 32 |
|
46 | | -If you're using `FluentAssertions` in your test project, the companion assertions package is available here: |
47 | | -[FixedMathSharp.FluentAssertions](https://www.nuget.org/packages/FixedMathSharp.FluentAssertions) |
| 33 | +- Maximum numeric range or hardware throughput. |
| 34 | +- Rendering, shader, animation, and visual-only calculations. |
| 35 | +- Interop with engines or APIs that already own their float-based math pipeline. |
48 | 36 |
|
49 | | -### Build From Source |
| 37 | +--- |
50 | 38 |
|
51 | | -Clone the repository and build locally: |
| 39 | +## Features |
52 | 40 |
|
53 | | -```bash |
54 | | -git clone https://github.com/mrdav30/FixedMathSharp.git |
55 | | -dotnet restore |
56 | | -dotnet build --configuration Debug --no-restore |
57 | | -``` |
| 41 | +- **`Fixed64` scalar arithmetic** with deterministic Q32.32 representation, guarded overflow behavior, parsing, formatting, and common math helpers. |
| 42 | +- **2D, 3D, and 4D vectors** via `Vector2d`, `Vector3d`, and `Vector4d`, including dot products, distances, normalization, transforms, fuzzy equality, and component operations. |
| 43 | +- **Rotations and matrices** with `FixedQuaternion`, `Fixed3x3`, and `Fixed4x4` for deterministic transforms and orientation math. |
| 44 | +- **Geometry and bounds** with `BoundingBox`, `BoundingSphere`, `BoundingArea`, `BoundingFrustum`, `FixedPlane`, and `FixedRay`. |
| 45 | +- **Curves and ranges** with `FixedCurve`, `FixedCurveKey`, and `FixedRange`. |
| 46 | +- **Deterministic RNG** with `DeterministicRandom` streams derived from seeds, feature keys, and indices. |
| 47 | +- **Serialization-friendly structs** with MemoryPack support in the standard package and a Lean package when you do not want that dependency. |
| 48 | +- **Testing helpers** through the companion FluentAssertions package. |
58 | 49 |
|
59 | | -You can also reference the project directly or consume the generated package artifacts in your own build process. |
60 | | - |
61 | | -### Package Variants |
| 50 | +--- |
62 | 51 |
|
63 | | -The published NuGet packages map directly to the source-build configurations below. |
| 52 | +## Installation |
64 | 53 |
|
65 | | -If you build from source, the repository also provides matching release configurations: |
| 54 | +For most .NET projects: |
66 | 55 |
|
67 | | -- `Release` builds the standard `FixedMathSharp` package and archives. |
68 | | -- `ReleaseLean` builds the `FixedMathSharp.Lean` package and archives. |
| 56 | +```bash |
| 57 | +dotnet add package FixedMathSharp |
| 58 | +``` |
69 | 59 |
|
70 | | -If you use Unity Burst AOT, prefer the `Lean` variant. |
| 60 | +Choose the package that fits your runtime: |
71 | 61 |
|
72 | | -### Unity Integration |
| 62 | +| Package | Best For | Install | |
| 63 | +| --- | --- | --- | |
| 64 | +| `FixedMathSharp` | Most .NET applications. Includes MemoryPack support. | `dotnet add package FixedMathSharp` | |
| 65 | +| `FixedMathSharp.Lean` | Projects that want the same math API without a MemoryPack dependency, including custom serializers and Burst AOT-sensitive workflows. | `dotnet add package FixedMathSharp.Lean` | |
| 66 | +| `FixedMathSharp.FluentAssertions` | Tests that use FluentAssertions with `Fixed64`, vectors, quaternions, and matrices. | `dotnet add package FixedMathSharp.FluentAssertions` | |
| 67 | +| `FixedMathSharp.FluentAssertions.Lean` | FluentAssertions helpers paired with the Lean package. | `dotnet add package FixedMathSharp.FluentAssertions.Lean` | |
73 | 68 |
|
74 | | -FixedMathSharp is maintained as a separate Unity package. For Unity-specific implementations, refer to: |
| 69 | +### Unity |
75 | 70 |
|
76 | | -🔗 [FixedMathSharp-Unity Repository](https://github.com/mrdav30/FixedMathSharp-Unity). |
| 71 | +FixedMathSharp is maintained separately for Unity-specific packaging and workflows: |
| 72 | +[FixedMathSharp-Unity](https://github.com/mrdav30/FixedMathSharp-Unity). |
77 | 73 |
|
78 | | -If you are evaluating this .NET package for Unity-adjacent tooling using Burst AOT, prefer `FixedMathSharp.Lean`. |
| 74 | +If you are evaluating this .NET package for Unity-adjacent tooling or Burst AOT-sensitive code, prefer `FixedMathSharp.Lean`. |
79 | 75 |
|
80 | 76 | --- |
81 | 77 |
|
82 | | -## 📖 Usage Examples |
83 | | - |
84 | | -### Basic Arithmetic with `Fixed64` |
| 78 | +## Quick Start |
85 | 79 |
|
86 | 80 | ```csharp |
87 | | -Fixed64 a = new Fixed64(1.5); |
88 | | -Fixed64 b = new Fixed64(2.5); |
89 | | -Fixed64 result = a + b; |
90 | | -Console.WriteLine(result); // Output: 4.0 |
91 | | -``` |
| 81 | +using FixedMathSharp; |
92 | 82 |
|
93 | | -### Vector Operations |
| 83 | +Fixed64 speed = new Fixed64(3.5); |
| 84 | +Fixed64 deltaTime = Fixed64.Fraction(1, 60); |
| 85 | +Fixed64 step = speed * deltaTime; |
94 | 86 |
|
95 | | -```csharp |
96 | | -Vector3d v1 = new Vector3d(1, 2, 3); |
97 | | -Vector3d v2 = new Vector3d(4, 5, 6); |
98 | | -Fixed64 dotProduct = Vector3d.Dot(v1, v2); |
99 | | -Console.WriteLine(dotProduct); // Output: 32 |
100 | | -``` |
| 87 | +Vector3d position = new Vector3d(0, 0, 0); |
| 88 | +Vector3d velocity = new Vector3d(step, Fixed64.Zero, Fixed64.One); |
101 | 89 |
|
102 | | -### Quaternion Rotation |
| 90 | +FixedQuaternion turn = FixedQuaternion.FromAxisAngle(Vector3d.Up, FixedMath.PiOver2); |
| 91 | +Vector3d rotated = turn.Rotate(velocity); |
103 | 92 |
|
104 | | -```csharp |
105 | | -FixedQuaternion rotation = FixedQuaternion.FromAxisAngle(Vector3d.Up, FixedMath.PiOver2); // 90 degrees around Y-axis |
106 | | -Vector3d point = new Vector3d(1, 0, 0); |
107 | | -Vector3d rotatedPoint = rotation.Rotate(point); |
108 | | -Console.WriteLine(rotatedPoint); // Output: (0, 0, -1) |
109 | | -``` |
| 93 | +BoundingSphere sensor = new BoundingSphere(position, new Fixed64(5)); |
| 94 | +bool inRange = sensor.Contains(rotated); |
110 | 95 |
|
111 | | -### Matrix Transformations |
112 | | - |
113 | | -```csharp |
114 | | -Fixed4x4 matrix = Fixed4x4.Identity; |
115 | | -Vector3d position = new Vector3d(1, 2, 3); |
116 | | -matrix.SetTransform(position, Vector3d.One, FixedQuaternion.Identity); |
117 | | -Console.WriteLine(matrix); |
| 96 | +Console.WriteLine($"{rotated} in range: {inRange}"); |
118 | 97 | ``` |
119 | 98 |
|
120 | | -### Bounding Shapes and Intersection |
| 99 | +### Deterministic Random Streams |
121 | 100 |
|
122 | 101 | ```csharp |
123 | | -BoundingBox box = new BoundingBox(new Vector3d(0, 0, 0), new Vector3d(5, 5, 5)); |
124 | | -BoundingSphere sphere = new BoundingSphere(new Vector3d(3, 3, 3), new Fixed64(1)); |
125 | | -bool intersects = box.Intersects(sphere); |
126 | | -Console.WriteLine(intersects); // Output: True |
127 | | -``` |
| 102 | +ulong worldSeed = 123456789UL; |
128 | 103 |
|
129 | | -### Trigonometry Example |
| 104 | +var oreRng = DeterministicRandom.FromWorldFeature(worldSeed, featureKey: 0xC0FFEEUL); |
| 105 | +var riverRng = DeterministicRandom.FromWorldFeature(worldSeed, featureKey: 0xBADC0DEUL, index: 3); |
130 | 106 |
|
131 | | -```csharp |
132 | | -Fixed64 angle = FixedMath.PiOver4; // 45 degrees |
133 | | -Fixed64 sinValue = FixedTrigonometry.Sin(angle); |
134 | | -Console.WriteLine(sinValue); // Output: ~0.707 |
| 107 | +Fixed64 oreRichness = oreRng.NextFixed64(Fixed64.Zero, new Fixed64(10)); |
| 108 | +Fixed64 riverBend = riverRng.NextFixed64(-Fixed64.One, Fixed64.One); |
| 109 | +int lootCount = oreRng.Next(1, 5); // [1, 5) |
135 | 110 | ``` |
136 | 111 |
|
137 | | -### Deterministic Random Generation |
138 | | - |
139 | | -Use `DeterministicRandom` when you need reproducible random values across runs, worlds, or features. |
140 | | -Streams are derived from a seed and remain deterministic regardless of threading or platform. |
| 112 | +### Bounds and Geometry |
141 | 113 |
|
142 | 114 | ```csharp |
143 | | -// Simple constructor-based stream: |
144 | | -var rng = new DeterministicRandom(42UL); |
145 | | - |
146 | | -// Deterministic integer: |
147 | | -int value = rng.Next(1, 10); // [1,10) |
148 | | -
|
149 | | -// Deterministic Fixed64 in [0,1): |
150 | | -Fixed64 ratio = rng.NextFixed6401(); |
| 115 | +BoundingBox room = new BoundingBox(Vector3d.Zero, new Vector3d(10, 4, 10)); |
| 116 | +FixedRay ray = new FixedRay(new Vector3d(-20, 0, 0), Vector3d.Right); |
151 | 117 |
|
152 | | -// One stream per “feature” that’s stable for the same worldSeed + key: |
153 | | -var rngOre = DeterministicRandom.FromWorldFeature(worldSeed: 123456789UL, featureKey: 0xORE); |
154 | | -var rngRivers = DeterministicRandom.FromWorldFeature(123456789UL, 0xRIV, index: 0); |
| 118 | +Fixed64? hitDistance = ray.Intersects(room); |
155 | 119 |
|
156 | | -// Deterministic Fixed64 draws: |
157 | | -Fixed64 h = rngOre.NextFixed64(Fixed64.One); // [0, 1) |
158 | | -Fixed64 size = rngOre.NextFixed64(Fixed64.Zero, 5 * Fixed64.One); // [0, 5) |
159 | | -Fixed64 posX = rngRivers.NextFixed64(-Fixed64.One, Fixed64.One); // [-1, 1) |
160 | | -
|
161 | | -// Deterministic integers: |
162 | | -int loot = rngOre.Next(1, 5); // [1,5) |
| 120 | +if (hitDistance.HasValue) |
| 121 | +{ |
| 122 | + Vector3d hitPoint = ray.Position + (ray.Direction * hitDistance.Value); |
| 123 | + Console.WriteLine(hitPoint); |
| 124 | +} |
163 | 125 | ``` |
164 | 126 |
|
165 | | ---- |
166 | | - |
167 | | -## 📦 Library Structure |
| 127 | +### Matrices and Transforms |
168 | 128 |
|
169 | | -- **`Fixed64` Struct:** Core Q32.32 fixed-point scalar type. |
170 | | -- **`Vector2d` and `Vector3d` Structs:** 2D and 3D vector math. |
171 | | -- **`FixedQuaternion` Struct:** Deterministic quaternion rotations. |
172 | | -- **`Fixed4x4` and `Fixed3x3`:** Matrix math for transforms and orientation. |
173 | | -- **`IBound` Interface and bounds types:** `BoundingBox`, `BoundingArea`, and `BoundingSphere` for intersection, containment, and projection queries. |
174 | | -- **`FixedMath` and `FixedTrigonometry`:** Shared numeric and trigonometric helpers. |
175 | | -- **`DeterministicRandom` Struct:** Seedable, allocation-free RNG for repeatable procedural generation. |
176 | | - |
177 | | -### Fixed64 Struct |
| 129 | +```csharp |
| 130 | +FixedQuaternion rotation = FixedQuaternion.FromAxisAngle(Vector3d.Up, FixedMath.PiOver4); |
| 131 | +Fixed4x4 transform = Fixed4x4.CreateTranslation(new Vector3d(10, 0, 0)) * |
| 132 | + Fixed4x4.CreateRotation(rotation); |
178 | 133 |
|
179 | | -`Fixed64` is the center of the library: a deterministic fixed-point number type backed by integer arithmetic. It is the type used throughout the vector, matrix, quaternion, bounds, and helper APIs. |
| 134 | +Vector3d transformed = Fixed4x4.TransformPoint(transform, new Vector3d(1, 0, 0)); |
| 135 | +``` |
180 | 136 |
|
181 | 137 | --- |
182 | 138 |
|
183 | | -## ⚡ Performance Considerations |
| 139 | +## Library Map |
184 | 140 |
|
185 | | -FixedMathSharp is optimized for high-performance deterministic calculations: |
186 | | - |
187 | | -- **Inline methods and bit-shifting optimizations** keep hot paths lightweight. |
188 | | -- **Deterministic arithmetic** avoids floating-point drift in lockstep or replay-driven systems. |
189 | | -- **Fuzzy equality helpers** are available where precision tolerances are useful. |
| 141 | +- `Fixed64`: deterministic scalar type backed by a signed 64-bit raw value. |
| 142 | +- `FixedMath`: constants, rounding, interpolation, trigonometry, powers, square roots, and utility math. |
| 143 | +- `Vector2d`, `Vector3d`, `Vector4d`: deterministic vector math and transform helpers. |
| 144 | +- `FixedQuaternion`, `Fixed3x3`, `Fixed4x4`: rotations, orientations, matrices, and transform operations. |
| 145 | +- `BoundingBox`, `BoundingSphere`, `BoundingArea`, `BoundingFrustum`: containment, intersection, clamping, and projection queries. |
| 146 | +- `FixedPlane`, `FixedRay`: geometric primitives for plane classification and ray intersections. |
| 147 | +- `FixedCurve`, `FixedCurveKey`, `FixedRange`: interpolation and range helpers. |
| 148 | +- `DeterministicRandom`: repeatable random streams for simulations and procedural generation. |
| 149 | +- `FixedMathSharp.FluentAssertions`: expressive test assertions for FixedMathSharp types. |
190 | 150 |
|
191 | 151 | --- |
192 | 152 |
|
193 | | -## 🧪 Testing and Validation |
194 | | - |
195 | | -The library is covered by xUnit tests for core arithmetic, vectors, bounds, serialization, and deterministic random behavior. Fuzzy comparisons are used where a tolerance-based check is more appropriate than exact equality. |
196 | | - |
197 | | -Cyclomatic complexity exceptions are tracked in [`docs/complexity-exceptions.md`](docs/complexity-exceptions.md). The register explains why specific hot-path or fixed-shape methods exceed the review threshold and what should trigger revisiting them. |
198 | | - |
199 | | -To run the tests: |
| 153 | +## Build From Source |
200 | 154 |
|
201 | 155 | ```bash |
202 | | -dotnet test --configuration Debug |
| 156 | +git clone https://github.com/mrdav30/FixedMathSharp.git |
| 157 | +cd FixedMathSharp |
| 158 | +dotnet restore |
| 159 | +dotnet build --configuration Debug --no-restore |
| 160 | +dotnet test --configuration Debug --no-build |
203 | 161 | ``` |
204 | 162 |
|
205 | | ---- |
| 163 | +Release build configurations: |
206 | 164 |
|
207 | | -## 🛠️ Compatibility |
| 165 | +- `Release` builds the standard package. |
| 166 | +- `ReleaseLean` builds the Lean package with MemoryPack excluded. |
208 | 167 |
|
209 | | -- **.NET Standard** 2.1 |
210 | | -- **.NET** 8 |
211 | | -- **Unity 2020+** (via [FixedMathSharp-Unity](https://github.com/mrdav30/FixedMathSharp-Unity)) |
212 | | -- **Cross-Platform Support** (Windows, Linux, macOS) |
| 168 | +The helper script `.assets/scripts/set-version-and-build.ps1` builds both release configurations and writes release archives to `artifacts/releases/`. |
213 | 169 |
|
214 | 170 | --- |
215 | 171 |
|
216 | | -## 🤝 Contributing |
| 172 | +## Compatibility |
217 | 173 |
|
218 | | -We welcome contributions! Please see our [CONTRIBUTING](https://github.com/mrdav30/FixedMathSharp/blob/main/CONTRIBUTING.md) guide for details on how to propose changes, report issues, and interact with the community. |
| 174 | +- .NET Standard 2.1 |
| 175 | +- .NET 8 |
| 176 | +- Windows, Linux, and macOS |
219 | 177 |
|
220 | 178 | --- |
221 | 179 |
|
222 | | -## 👥 Contributors |
223 | | - |
224 | | -- **mrdav30** - Lead Developer |
225 | | -- Contributions are welcome! Feel free to submit pull requests or report issues. |
| 180 | +## Quality Notes |
226 | 181 |
|
227 | | ---- |
| 182 | +The library is covered by xUnit tests for arithmetic, vectors, matrices, quaternions, bounds, curves, serialization, deterministic random behavior, and FluentAssertions helpers. |
228 | 183 |
|
229 | | -## 💬 Community & Support |
| 184 | +Cyclomatic complexity exceptions are tracked in [`docs/complexity-exceptions.md`](docs/complexity-exceptions.md). The register explains why specific hot-path or fixed-shape methods exceed the review threshold and what should trigger revisiting them. |
230 | 185 |
|
231 | | -For questions, discussions, or general support, join the official Discord community: |
| 186 | +--- |
232 | 187 |
|
233 | | -👉 **[Join the Discord Server](https://discord.gg/mhwK2QFNBA)** |
| 188 | +## Contributing |
234 | 189 |
|
235 | | -For bug reports or feature requests, please open an issue in this repository. |
| 190 | +Contributions, bug reports, feature requests, and real-world determinism stories are welcome. Please read the [CONTRIBUTING](https://github.com/mrdav30/FixedMathSharp/blob/main/CONTRIBUTING.md) guide before opening a pull request. |
236 | 191 |
|
237 | | -We welcome feedback, contributors, and community discussion across all projects. |
| 192 | +For questions and discussion, join the official Discord community: |
| 193 | +[Join the Discord Server](https://discord.gg/mhwK2QFNBA) |
238 | 194 |
|
239 | 195 | --- |
240 | 196 |
|
241 | | -## 📄 License |
| 197 | +## License |
242 | 198 |
|
243 | | -This project is licensed under the MIT License. |
| 199 | +FixedMathSharp is licensed under the MIT License. |
244 | 200 |
|
245 | | -See the following files for details: |
| 201 | +See these repository files for details: |
246 | 202 |
|
247 | | -- LICENSE – standard MIT license |
248 | | -- NOTICE – additional terms regarding project branding and redistribution |
249 | | -- COPYRIGHT – authorship information |
| 203 | +- `LICENSE` - standard MIT license. |
| 204 | +- `NOTICE` - additional terms regarding project branding and redistribution. |
| 205 | +- `COPYRIGHT` - authorship information. |
0 commit comments