This repository contains a C++20 implementation of the classic Quake III fast inverse‑square‑root algorithm, along with highly‑optimised SIMD batch variants. The code is portable across Windows (MSVC or clang‑cl), Linux and macOS (Only Windows tested), supports SSE, AVX2 and AVX‑512 when available, and includes a small test harness and benchmark.
- Scalar fast inverse square root (
FastInverseSqrt) – one Newton–Raphson iteration on a 32‑bit float. - Hardware reciprocal square root (
InverseSqrtSIMD) – single‑step_mm_rsqrt_ssfor a scalar value, and_mm_rsqrt_psfor a batch of four floats. - Batch SIMD implementation (
FastInverseSqrtBatch) – processes an array offloats in 4/8/16‑wide chunks using SSE/AVX2/AVX‑512 respectively. The vector width is chosen automatically at compile time, but dedicated overloads are available for AVX2 and AVX‑512. - Portable API – all functions live in the
fisqnamespace; overloads accept either raw pointers with size orstd::spanfor ergonomics. - C++20 only – uses
<bit>,<concepts>and other modern features.
The project is built with CMake and ships several presets that configure a release build for the most common toolchains. All builds target an x86‑64 CPU; SSE support is required by default, while AVX2/AVX‑512 are optional and can be enabled via dedicated presets.
# Configure a Release build with the default preset
cmake --preset x64-release
# Build the library, tests and benchmark
cmake --build out\build\x64-release --config ReleaseIf you want to target AVX‑512 you can use the dedicated preset:
cmake --preset avx512-release
cmake --build out\build\avx512-release --config Release# Configure a Release build with the default preset
cmake --preset x64-release
# Build everything
cmake --build out/build/x64-release --config ReleaseUse cmake --preset avx512-release for AVX‑512 builds on Linux/macOS as well.
The presets automatically set the compiler (clang-cl.exe, cl.exe, gcc or clang++) and enable C++20. You can also use standard CMake arguments if you prefer a custom build directory.
#include "fast_inverse_sqrt.hpp"
#include <iostream>
#include <vector>
int main() {
// Scalar usage
float value = 4.0f;
std::cout << "FastInverseSqrt(" << value << ") = "
<< fisq::FastInverseSqrt(value) << '\n';
// Batch processing with automatic SIMD selection
std::vector<float> data{1.f, 2.f, 3.f, 4.f};
std::vector<float> out(data.size());
fisq::FastInverseSqrtBatch(std::as_const(data), out);
for (float v : out)
std::cout << v << ' ';
}Compile with a C++20 compiler and link against the static library fisq.lib/libfisq.a. The header can also be used as a header‑only solution by including it in your project; no separate build is required.
- Parameters:
number– a 32‑bit floating point value. - Returns: Approximate value of
1 / sqrt(number)after one Newton–Raphson iteration. - Behavior:
- Positive, finite inputs: relative error ≤ 0.2 % (verified by the unit tests).
0→ large finite number (~ 1.98 × 10¹⁹), effectively representing infinity.- Negative numbers → NaN.
- ±∞ or NaN propagate unchanged.
- Parameters:
number– a 32‑bit floating point value. - Returns: Approximate value of
1 / sqrt(number)using the single‑step_mm_rsqrt_ss. - Behavior:
- Positive, finite inputs: relative error ≤ 0.6 % (no Newton refinement).
0→ IEEE infinity.- Negative numbers → NaN.
- Parameters:
src– input values.dst– output buffer (must be pre‑allocated and the same size assrc).
- Description: Processes the array in chunks of 4/8/16 floats depending on the available SIMD width. The function is safe to call with any length; elements that do not fill a full vector are ignored, so callers should pass sizes that are multiples of the chosen width.
- Description: Same as above but uses SSE intrinsics (
_mm_rsqrt_ps) and requires the size to be a multiple of 4.
void FastInverseSqrtAVX2Batch(std::span<const float> src, std::span<float> dst) noexcept (conditionally compiled)
- Description: AVX2 implementation; requires the length to be a multiple of 8. Only available when compiling with AVX2 support (
__AVX__ && __AVX2__).
void FastInverseSqrtAVX512Batch(std::span<const float> src, std::span<float> dst) noexcept (conditionally compiled)
- Description: AVX‑512 implementation; requires the length to be a multiple of 16. Only available when compiling with AVX‑512 support (
__AVX512F__).
All batch functions also have overloads that accept const float* src, float* dst and a size parameter, which are useful in low‑level code or when interfacing with legacy APIs.
The repository ships benchmark.cpp, which measures execution time (in milliseconds) and prints detailed error metrics for each variant. Example output on an Intel CPU:
Warm-up iterations: 5
Iterations per function: 1000000
Total elapsed time (ms): 2.1601
Time
Q3(C++20): 4.3970e-01 ms (avg=4.3970e-01 ns)
Q3(SIMD): 2.9590e-01 ms (avg=2.9590e-01 ns)
RSqrt(SIMD): 1.0796e+00 ms (avg=1.0796e+00 ns)
Std: 1.4245e+00 ms
Error metrics
mean_abs, max_abs, mean_rel
Q3(C++20): 0x1.f2fc97efe0ce1p-15, 0x1.47ec000000000p-8, 0x1.f82dc4cee149ap-11
Q3(SIMD): 0x1.3e75bc44bf4cbp-29, 0x1.0000000000000p-21, 0x1.39df740d6494dp-25
RSqrt(SIMD): 0x1.91c80a2877ee5p-18, 0x1.7a60000000000p-11, 0x1.8ded4c7a47243p-14
Checksums -> Q3 (C++20): 0x1.e85653c9d2000p+15, Q3(SIMD): 0x1.e8cd4b2584400p+15, RSqrt(SIMD): 0x1.e8cd509700000p+15, Std: 0x1.e8cd4b8475800p+15
When building with AVX‑512 support the benchmark also reports Q3(AVX512) and Q3(AVX2). The SIMD variant is roughly 30 % faster than the classic implementation and competitive with the standard library.
Unit tests are located in tests/test_fast_inverse_sqrt.cpp. They validate:
- Correctness of all scalar functions against the exact value
1 / sqrt(x)with a relative‑error tolerance of 0.2 %. - Correctness of batch functions on small, medium and large input sizes.
- Edge cases: zero (expects infinity for
InverseSqrtSIMDand a large finite number forFastInverseSqrt), negative numbers (expect NaN), random values in the range[1e‑30, 1e+38].
Run the tests with:
# From the build directory
./fisq_tests.exe # on Windows
./fisq_tests # on Linux/macOSor use CTest:
ctest -VAll tests should pass.
This project is released into the public domain under the CC0 1.0 Universal license.