Crafter.Math/README.md
Jorijn van der Graaf 087c8b32c3
feat: quaternion operations, and transforms that mean the same in 4x4 and 4x3
- A 4-vector doubles as a unit quaternion in (x, y, z, w) order:
  QuanternionMultiply, QuanternionConjugate, QuanternionFromAxisAngle,
  QuanternionFromUnitVectors (shortest arc), QuanternionNlerp and
  QuanternionSlerp, next to the existing QuanternionFromBasis.
- MatrixRowMajor gains Rotation (from a quaternion), TRS, InverseAffine,
  Transpose and Decompose. The 4x4 transforms row vectors and the 4x3
  column vectors (the VkTransformMatrixKHR layout); each of these means the
  same transform in both. The 4x3 Rotation copied the 4x4's rows, which
  rotated by the inverse.
- The static Normalize no longer assumes three components.
- Tests: Quaternion, and Matrix extended.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 19:07:06 +02:00

75 lines
5.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Crafter.Math
A C++23 math library for the Crafter engine, distributed as a set of C++ modules. Provides generic vector and matrix types alongside SIMD-specialized fixed-size vectors for `float` and `_Float16`, plus a small set of ray intersection routines.
The library is hardware-aware: it picks the widest SIMD path the target supports (SSE / AVX / AVX-512 on x86_64, NEON on AArch64, RVV on RISC-V, SIMD128 on WebAssembly) and falls back to scalar code elsewhere.
## Modules
`import Crafter.Math;` re-exports the following partitions:
| Partition | Contents |
| --- | --- |
| `:Basic` | `ToRadian`, plus the `VectorF16 → VectorF32` alias on x86_64 without AVX512-FP16 and on AArch64 without ARMv8.2-FP16. |
| `:Vector` | Generic `Vector<T, Len, Alignment>` with `.x/.y/.z/.w` and `.r/.g/.b/.a` accessors, arithmetic, comparison, and conversion operators. A 4-vector doubles as a unit quaternion in (x, y, z, w) order: `Rotate` applies one, and `QuanternionMultiply`, `QuanternionConjugate`, `QuanternionFromAxisAngle`, `QuanternionFromUnitVectors` (shortest arc), `QuanternionFromBasis`, `QuanternionFromEuler`, `QuanternionNlerp` and `QuanternionSlerp` build and combine them. |
| `:MatrixRowMajor` | `MatrixRowMajor<T, ColumnSize, RowSize, Repeats>` — row-major matrices with packed-batch support via `Repeats`. The 4x4 transforms row vectors (`v * M`, translation in row 3) and the 4x3 column vectors (`M * v`, translation in column 3, the `VkTransformMatrixKHR` layout); `Rotation`, `TRS` (from a translation, quaternion and scale), `InverseAffine` and `Decompose` mean the same transform in both. |
| `:VectorF32` | `VectorF32<Len, Packing>` — SIMD-specialized 32-bit float vector with `Load`/`Store`, FMA, `Cross`, `Dot`, `Length`, `Normalize`, `Sin`/`Cos`, `Shuffle`, etc. |
| `:VectorF16` | `VectorF16<Len, Packing>` — same surface as `VectorF32` for `_Float16` when the target supports it. |
| `:Intersection` | `IntersectionTestRayTriangle`, `IntersectionTestRaySphere`, `IntersectionTestRayOrientedBox`. |
| `:Common` | Internal SIMD type selection (`__m128/256/512`, `__m128h/256h/512h`, `float32x4_t`, `float16x8_t`, `v128_t`, or scalar array) used by the F16/F32 vectors. |
`Len` is the logical vector width (1–4 for most graphics use) and `Packing` is the number of vectors packed into one SIMD register — e.g. `VectorF32<3, 4>` holds four 3-vectors in a single 512-bit register, which is what the batched `Dot`, `Length`, and `Normalize` overloads operate on.
## Example
```cpp
import Crafter.Math;
using namespace Crafter;
// Generic 3-vector of floats.
Vector<float, 3> a(1.0f, 2.0f, 3.0f);
Vector<float, 3> b(4.0f, 5.0f, 6.0f);
auto c = a + b;
// SIMD-specialized 4-vector with one element of padding.
VectorF32<4, 1> p(1.0f);
VectorF32<4, 1> q(2.0f);
auto r = VectorF32<3, 1>::Cross(p, q);
// Ray vs. triangle.
float t = IntersectionTestRayTriangle<float>(
{0,0,0}, {1,0,0}, {0,1,0},
{0.25f, 0.25f, -1.0f}, {0, 0, 1});
```
## Building
This project uses [Crafter.Build](https://forgejo.catcrafts.net/Catcrafts/Crafter.Build). The build script in [project.cpp](project.cpp) declares the library as a static C++ module library and registers three test executables targeting different ISAs:
- `Vector-sapphirerapids` — AVX-512 with FP16 (`-march=sapphirerapids`)
- `Vector-x86-64-v4` — AVX-512 baseline
- `Vector-x86-64-v3` — AVX2 baseline
- `Vector-rv64gcv_zvl512b` — RVV with VLEN≥512 (uses the 64-byte tier)
- `Vector-rv64gcv_zvl256b` — RVV with VLEN≥256 (32-byte tier)
- `Vector-rv64gcv` — RVA23 baseline ZVL128B (16-byte tier)
- `Vector-armv8.2-a+fp16` — AArch64 NEON with ARMv8.2-FP16 (native `VectorF16`)
- `Vector-armv8-a` — AArch64 baseline NEON
Build and run tests via your usual Crafter.Build entry point; `build/` and `bin/` are git-ignored.
## Target support
- **x86_64**: SSE / AVX / AVX-512F selected per target; AVX512-FP16 is required for native `VectorF16` (otherwise it aliases `VectorF32`). F16C is used for fp16 ↔ fp32 conversion when available.
- **RISC-V**: RVV 1.0 (the `V` extension, ratified Nov 2021, mandatory in the RVA23 profile). Storage is a 16/32/64-byte GNU vector picked at compile time from the guaranteed VLEN (`__riscv_v_fixed_vlen` from Clang's `-mrvv-vector-bits=`, else `__riscv_v_min_vlen` from the march's `Zvl*` suffix, else the ZVL128B baseline). `VectorF16` aliases `VectorF32` until a `Zvfh` path lands.
- **AArch64**: NEON (`arm_neon.h`) 128-bit path; SIMD width is capped at 16 bytes, so a vector holds at most 4 floats or 8 halves. `VectorF32` only needs the ARMv8-A baseline. ARMv8.2-FP16 (`-march=armv8.2-a+fp16`, or any `-march`/`-mcpu` that implies it) is required for native `VectorF16`; otherwise it aliases `VectorF32`, which converts fp16 ↔ fp32 on `Load`/`Store`. 32-bit ARM takes the scalar fallback.
- **WebAssembly**: `wasm_simd128.h` 128-bit path; SIMD width is capped at 16 bytes.
- **Other targets**: scalar fallback via `std::array<T, N>`.
## License
This library is licensed under the GNU Lesser General Public License, version 3 only (LGPL-3.0-only). See [LICENSE](LICENSE) for the license text. The LGPL supplements the GNU General Public License version 3, a copy of which is included as [LICENSE.GPL](LICENSE.GPL).
## Copyright
Copyright (C) 2026 Catcrafts®
catcrafts.net