C++ math library with a focus on templates.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-10-31 18:28:15 +01:00
interfaces AGENTS.md 2026-10-31 06:52:22 +01:00
tests AGENTS.md 2026-10-31 06:52:22 +01:00
.gitattributes LF line endings 2026-10-06 16:59:52 +02:00
.gitignore chagned to agents.md template 2026-10-31 18:28:15 +01:00
AGENTS.consumer.md AGENTS.md 2026-10-31 06:52:22 +01:00
AGENTS.template.md chagned to agents.md template 2026-10-31 18:28:15 +01:00
LICENSE updated project 2025-05-07 19:18:58 +02:00
LICENSE.GPL SPDX license update 2026-07-22 18:01:26 +02:00
project.cpp feat: quaternion operations, and transforms that mean the same in 4x4 and 4x3 2026-10-20 19:07:06 +02:00
README.md feat: quaternion operations, and transforms that mean the same in 4x4 and 4x3 2026-10-20 19:07:06 +02:00

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

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. The build script in 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 for the license text. The LGPL supplements the GNU General Public License version 3, a copy of which is included as LICENSE.GPL.

Copyright (C) 2026 Catcrafts® catcrafts.net