Skip to main content

High-performance cross-platform 128-bit arithmetic for SIMD applications.

Project description

simd-f128 Logo
High-performance cross-platform 128-bit arithmetic for SIMD applications.

simd-f128

Linux macOS Windows WASM Mobile PyPI NPM

License: MIT Language Language Header-Only Zero-Allocation No-Dependencies Last Commit

Read the Official Documentation: docs/index.md
Try the Live WebAssembly Demo: https://tiw302.github.io/simd-f128/demo/

Verified Compatibility — 11/11 Platforms Passing

Architecture Platform Verified Backend
x86_64 (Modern) Linux / Windows AVX2 (Vectorized)
x86_64 (Legacy) Linux SSE2 (Emulated SIMD)
ARM64 (Apple) macOS (M1/M2/M3) NEON (Vectorized)
ARM64 (Android) Mobile NEON (Vectorized)
ARMv7 (Android) Mobile Scalar C11
WebAssembly Chrome / Node.js WASM-SIMD128
WebAssembly Universal Web WASM Scalar
RISC-V64 Linux (QEMU) Scalar C11
General Desktop Linux / Windows Scalar C11 Fallback

Table of Contents

Introduction Setup & Build Components Resources Community
Overview Requirements Core Engine API Docs CI Status
Why? Toolchains Constants Math Theory Contributing
Philosophy Installation I/O Utilities Examples License
Math Functions Limitations & Technical Notes
Utilities & Comparisons
C++ Wrapper

Introduction

simd-f128 is a professional-grade, header-only C library for 128-bit (Double-Double) floating-point arithmetic. It targets the precision gap between standard 64-bit IEEE 754 doubles and heavyweight arbitrary-precision libraries, providing approximately 31-32 decimal digits of accuracy with zero heap allocation overhead.

Designed for demanding workloads such as fractal rendering, physical simulations, and orbital mechanics — where double precision falls short but libquadmath or GMP would be excessive.


Why simd-f128?

Ever zoomed into a Mandelbrot set and watched the detail dissolve into grey mush? That's double precision dying — at zoom levels beyond ~10^-14, two distinct coordinates become the same value and the image collapses entirely. The same silent failure happens in long-running simulations, ill-conditioned linear algebra, and anywhere small errors compound over time.

The usual fixes each carry a significant cost:

Option Precision Allocation Portability Complexity
double ~15 digits None Universal None
long double 18-19 digits (x87) None Compiler-dependent Low
__float128 (GCC) ~33 digits None GCC/Clang only Medium
GMP / MPFR Arbitrary Heap Portable High
[x] simd-f128 ~31 digits None Universal Low

__float128 gets close on precision but locks you into GCC/Clang and is noticeably slower in tight loops. GMP/MPFR are powerful but heap-allocating inside a render loop is a non-starter.

simd-f128 occupies the exact gap: it doubles usable precision with zero allocation, zero dependencies, and no compiler lock-in — proven in practice by mandelbrot-c, which achieves stable deep-zoom rendering at coordinates down to 10^-28, far beyond what standard double can represent.


Design Philosophy

The library is built around three constraints that were never relaxed during development:

Zero allocation. Every operation executes entirely in CPU registers. There are no calls to malloc, no temporary buffers, and no GC pressure. This makes simd-f128 suitable for use inside tight render loops, interrupt handlers, and embedded firmware where heap allocation is prohibited.

No configuration required. The correct SIMD backend — AVX2, NEON, WASM-SIMD, or scalar — is selected automatically at compile time based on the target architecture. Passing the wrong flag produces a compile error immediately rather than silently degrading precision at runtime.

Standard C foundation. The library is built entirely on IEEE 754 double arithmetic and C11 standard library functions. It does not rely on compiler extensions, non-standard intrinsics outside of guarded #ifdef blocks, or platform-specific ABI assumptions. The scalar fallback compiles and produces correct results on any C99-compliant toolchain.


Limitations & Technical Notes

Double-Double vs IEEE 754 128-bit: Please note that simd-f128 uses Double-Double arithmetic (an unevaluated sum of two standard 64-bit double values) to achieve approximately 31 decimal digits of precision. It is not a strictly compliant IEEE 754 binary128 implementation.

While this approach offers massive performance benefits and is perfect for deeply zooming into fractals (like in mandelbrot-c, it is susceptible to Catastrophic Cancellation in specific scenarios (e.g., subtracting two nearly identical values). If you are building highly sensitive physics simulations or rigorous numerical analysis tools where IEEE 754 edge-case compliance is strictly required, a heavier library like GMP/MPFR or compiler-specific __float128 may be more appropriate.


Requirements

Component Requirement
C Standard C11 or later (C99 compatible for scalar path)
C++ Standard C++11 or later (for simd_f128.hpp only)
Compiler GCC 4.9+, Clang 3.5+, MSVC 2019+, Emscripten 3.0+
Math library -lm required on Linux/UNIX (for fma())

Verified Toolchains

The following toolchains are tested on every commit via CI. All others fall back to the scalar path and are expected to produce correct results.

Toolchain Version Platform Backend
GCC 11+ Linux x86_64 Scalar, AVX2
GCC (aarch64-linux-gnu) 11+ Linux ARM64 (QEMU) NEON
GCC (arm-linux-gnueabihf) 11+ Linux ARMv7 (QEMU) Scalar + VFPv4
GCC (riscv64-linux-gnu) 11+ Linux RISC-V64 (QEMU) Scalar
Clang 14+ macOS Apple Silicon NEON
Clang 14+ macOS Intel Scalar, AVX2
MSVC 2022 Windows x64 Scalar
Emscripten 3.0+ WASM (Node.js) WASM-SIMD, Scalar

Build and Installation

simd-f128 can be integrated natively via C/C++ headers, Python, or JavaScript (WebAssembly).

Python (PyPI)

pip install simd-f128

JavaScript / Node.js (NPM)

npm install @tiw302/simd-f128

C/C++ (Header Only)

simd-f128 is header-only. The simplest integration is copying the include/ directory directly into your project, then defining the implementation macro in exactly one translation unit:

#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.h>
#include <simd_f128_io.h>   // optional

All other translation units include the headers without the macro.

For C++ projects, include the convenience wrapper instead:

#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.hpp>   // pulls in all headers automatically

CMake

System Install (Recommended) You can install the library system-wide to easily use find_package in other projects:

cmake -S . -B build
sudo cmake --install build

Then in your project's CMakeLists.txt:

find_package(simd_fp REQUIRED)
target_link_libraries(my_app PRIVATE simd_fp::simd_fp)

Local Build Options

# Scalar backend (default - works everywhere)
cmake -S . -B build
cmake --build build

# AVX2 backend (Intel/AMD Haswell+)
cmake -S . -B build -DSIMD_F128_AVX2=ON
cmake --build build

# WebAssembly + SIMD128 (Chrome 91+, Firefox 89+, Safari 16.4+, Node.js 16+)
emcmake cmake -S . -B build -DSIMD_F128_WASM=ON
cmake --build build

# WebAssembly Scalar (maximum browser compatibility)
emcmake cmake -S . -B build
cmake --build build

# ARMv7 - optional flag for hardware FMA on VFPv4 cores
cmake -S . -B build -DCMAKE_C_FLAGS="-mfpu=neon-vfpv4 -mfloat-abi=hard"
cmake --build build

AArch64 (Apple Silicon, Graviton, Android ARM64) requires no flags - NEON is auto-detected. Run tests after building:

ctest --test-dir build

simd_f128.h (Core)

The central engine of the library. Implements the Double-Double type and all fundamental arithmetic operations. All functions are static inline - no separate compilation unit is needed beyond the SIMD_F128_IMPLEMENTATION guard.

Key properties:

  • ~106-bit mantissa - roughly 31-32 decimal digits of precision.
  • Zero heap allocation - all operations execute directly in CPU registers, suitable for tight inner loops.
  • Automatic SIMD dispatch - selects AVX2 (__m128d) on Intel/AMD, NEON (float64x2_t) on ARM64/Apple Silicon, WASM-SIMD (v128_t) on the web, or falls back to scalar C99.
  • Branchless implementation - consistent execution time, no pipeline stalls.
  • Strict IEEE 754 foundation - built on standard double, fully compatible with existing hardware.
#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.h>

int main() {
    simd_f128 a = simd_f128_from_double(1.234567890123456789);
    simd_f128 b = simd_f128_from_double(2.0);

    simd_f128 sum  = simd_f128_add(a, b);
    simd_f128 diff = simd_f128_sub(a, b);
    simd_f128 prod = simd_f128_mul(a, b);
    simd_f128 quot = simd_f128_div(a, b);
    simd_f128 root = simd_f128_sqrt(a);

    return 0;
}

simd_f128_consts.h

Pre-computed, high-precision mathematical constants stored as Double-Double pairs. Each constant captures the full ~106-bit mantissa, avoiding the precision loss inherent in standard 64-bit initialisers.

#include <simd_f128.h>
#include <simd_f128_consts.h>

int main() {
    simd_f128 pi     = SIMD_F128_PI;    // 3.14159265358979323846...
    simd_f128 e      = SIMD_F128_E;     // 2.71828182845904523536...
    simd_f128 sqrt_2 = SIMD_F128_SQRT2; // 1.41421356237309504880...
    simd_f128 ln2    = SIMD_F128_LN2;   // 0.69314718055994530941...

    return 0;
}

simd_f128_io.h

Handles conversion between the internal Double-Double representation and human-readable decimal strings. Standard printf formatting cannot faithfully render 128-bit values; this header uses an iterative high-precision extraction algorithm to produce up to 32 correct decimal places.

#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.h>
#include <simd_f128_io.h>

int main() {
    simd_f128 val = simd_f128_from_double(3.141592653589793);

    // direct console output
    simd_f128_print(val);

    // string conversion for logging or ui
    char buffer[128];
    simd_f128_to_string(buffer, sizeof(buffer), val);

    return 0;
}

simd_f128_math.h

Advanced mathematical functions built on top of the core Double-Double primitives. All functions are static inline and require no additional compilation unit.

Algorithms used:

  • exp — range reduction to $N=16$ intervals followed by a 12-degree Chebyshev minimax polynomial, then exact scaling via ldexp and a 16-entry lookup table. Handles overflow (> 709) and underflow (< -745) explicitly.
  • log — seeds from the standard double log(), then refines with 2 iterations of Halley's method (cubic convergence), which is sufficient to recover all 31-32 digits.
  • pow — computed as exp(exp * log(base)). Returns NaN for negative bases.
  • sin — range-reduces to quadrant ($[-\pi/4, \pi/4]$) then evaluates a 11-degree Chebyshev minimax polynomial.
  • cos — range-reduces to quadrant ($[-\pi/4, \pi/4]$) then evaluates a 11-degree Chebyshev minimax polynomial.
#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.h>
#include <simd_f128_consts.h>
#include <simd_f128_math.h>

int main() {
    simd_f128 x = SIMD_F128_PI;

    // e^π
    simd_f128 epi = simd_f128_exp(x);

    // ln(e) == 1
    simd_f128 one = simd_f128_log(SIMD_F128_E);

    // 2^10 == 1024
    simd_f128 base = simd_f128_from_double(2.0);
    simd_f128 exp  = simd_f128_from_double(10.0);
    simd_f128 pw   = simd_f128_pow(base, exp);

    // sin(π/6) == 0.5
    simd_f128 half_pi = simd_f128_mul(x, simd_f128_from_double(1.0 / 6.0));
    simd_f128 s       = simd_f128_sin(half_pi);

    // cos(0) == 1
    simd_f128 c = simd_f128_cos(simd_f128_from_double(0.0));

    return 0;
}

Note: sin and cos use a simplified range reduction suitable for moderate arguments. For very large inputs (|x| > ~10^15), consider applying Payne-Hanek argument reduction externally before calling these functions.


simd_f128_utils.h

Comparison operators and utility functions. All are static inline and work with any SIMD backend.

The foundation is simd_f128_cmp, which compares the hi components first and only falls through to the lo components when hi values are identical — matching the canonical Double-Double ordering rule.

#include <simd_f128.h>
#include <simd_f128_utils.h>

int main() {
    simd_f128 a = simd_f128_from_double(1.0);
    simd_f128 b = simd_f128_from_double(2.0);

    // comparisons
    int lt = simd_f128_lt(a, b);  // 1
    int eq = simd_f128_eq(a, b);  // 0
    int ge = simd_f128_ge(b, a);  // 1

    // utility
    simd_f128 neg = simd_f128_from_double(-3.14);
    simd_f128 abs_val = simd_f128_abs(neg);       // 3.14...
    simd_f128 lo      = simd_f128_min(a, b);      // 1.0
    simd_f128 hi      = simd_f128_max(a, b);      // 2.0

    return 0;
}

simd_f128.hpp

A modern C++ wrapper that makes simd_f128 feel like a native arithmetic type. Include this single header in C++ projects — it pulls in all other headers automatically.

Features:

  • f128::float128 class with full operator overloading (+, -, *, /, +=, -=, *=, /=).
  • Full interoperability with std::complex<double> via f128::complex128.
  • Seamless integration with the Eigen matrix library via simd_f128_eigen.hpp.
  • All six comparison operators (==, !=, <, >, <=, >=).
  • Unary negation (-x).
  • std::ostream integration (std::cout << val).
  • Free functions mirroring <cmath>: f128::exp, f128::log, f128::pow, f128::sin, f128::cos, f128::sqrt, f128::abs.
  • Predefined constants: f128::pi, f128::e, f128::sqrt2, f128::ln2.
#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.hpp>
#include <iostream>

int main() {
    f128::float128 a(1.5);
    f128::float128 b(2.5);

    // natural arithmetic
    f128::float128 sum  = a + b;
    f128::float128 prod = a * b;

    // math functions
    f128::float128 root = f128::sqrt(a);
    f128::float128 s    = f128::sin(f128::pi);

    // stream output
    std::cout << "a + b = " << sum  << "\n";
    std::cout << "a * b = " << prod << "\n";
    std::cout << "sqrt(a) = " << root << "\n";

    // comparisons
    if (a < b) {
        std::cout << "a is smaller\n";
    }

    return 0;
}

The float128 class stores a simd_f128 data member publicly, so it can be passed directly to any C API function when needed:

f128::float128 val(3.14);
simd_f128_print(val.data);  // call c api directly

API Reference

simd_f128.h

Function Signature Description
simd_f128_from_double simd_f128 simd_f128_from_double(double d) Promote a double to 128-bit. lo is initialised to 0.0.
simd_f128_extract void simd_f128_extract(simd_f128 x, double* hi, double* lo) Extract the hi and lo components into separate doubles.
simd_f128_add simd_f128 simd_f128_add(simd_f128 a, simd_f128 b) Double-Double addition via Knuth's TwoSum.
simd_f128_sub simd_f128 simd_f128_sub(simd_f128 a, simd_f128 b) Double-Double subtraction (negates b, then adds).
simd_f128_mul simd_f128 simd_f128_mul(simd_f128 a, simd_f128 b) Double-Double multiplication via Dekker's TwoProd + FMA.
simd_f128_div simd_f128 simd_f128_div(simd_f128 a, simd_f128 b) Double-Double division via Newton-Raphson reciprocal refinement.
simd_f128_sqrt simd_f128 simd_f128_sqrt(simd_f128 x) Square root via inverse-sqrt Newton-Raphson + residual correction.

simd_f128_consts.h

Constant Value (first 32 digits)
SIMD_F128_PI 3.14159265358979323846264338327950...
SIMD_F128_E 2.71828182845904523536028747135266...
SIMD_F128_SQRT2 1.41421356237309504880168872420969...
SIMD_F128_LN2 0.69314718055994530941723212145817...

simd_f128_io.h

Function Signature Description
simd_f128_print void simd_f128_print(simd_f128 x) Print the value to stdout followed by a newline.
simd_f128_to_string void simd_f128_to_string(char* buf, size_t buf_size, simd_f128 x) Write up to 32 decimal digits into buf. buf must be at least 64 bytes. Handles nan, inf, and negative values.

simd_f128_math.h

Function Signature Description
simd_f128_exp simd_f128 simd_f128_exp(simd_f128 x) e^x. Returns +Inf for x > 709, 0 for x < -745.
simd_f128_log simd_f128 simd_f128_log(simd_f128 x) Natural logarithm. Returns NaN for x ≤ 0.
simd_f128_pow simd_f128 simd_f128_pow(simd_f128 base, simd_f128 exp) base^exp. Returns 0 for base == 0, NaN for base < 0.
simd_f128_sin simd_f128 simd_f128_sin(simd_f128 x) Sine (radians). Best accuracy for moderate arguments.
simd_f128_cos simd_f128 simd_f128_cos(simd_f128 x) Cosine (radians). Implemented as sin(x + π/2).

simd_f128_utils.h

Function Signature Description
simd_f128_cmp int simd_f128_cmp(simd_f128 a, simd_f128 b) Returns -1 if a < b, 1 if a > b, 0 if equal.
simd_f128_eq int simd_f128_eq(simd_f128 a, simd_f128 b) 1 if a == b.
simd_f128_gt int simd_f128_gt(simd_f128 a, simd_f128 b) 1 if a > b.
simd_f128_lt int simd_f128_lt(simd_f128 a, simd_f128 b) 1 if a < b.
simd_f128_ge int simd_f128_ge(simd_f128 a, simd_f128 b) 1 if a >= b.
simd_f128_le int simd_f128_le(simd_f128 a, simd_f128 b) 1 if a <= b.
simd_f128_abs simd_f128 simd_f128_abs(simd_f128 x) Absolute value. Correctly handles -0.0 in the lo component.
simd_f128_min simd_f128 simd_f128_min(simd_f128 a, simd_f128 b) Returns the lesser of a and b.
simd_f128_max simd_f128 simd_f128_max(simd_f128 a, simd_f128 b) Returns the greater of a and b.

simd_f128.hpp (C++ only)

Symbol Kind Description
f128::float128 Class C++ wrapper around simd_f128.
f128::float128(double) Constructor Construct from a double.
f128::float128(simd_f128) Constructor Construct from a raw simd_f128.
float128::extract(hi, lo) Method Extract hi and lo components.
+, -, *, / Operators Arithmetic operators.
+=, -=, *=, /= Operators Compound assignment operators.
==, !=, <, >, <=, >= Operators Comparison operators.
operator-() Unary Negation.
float128::to_string() Method Returns std::string with 32-digit representation.
operator<< Stream std::ostream integration.
f128::exp, f128::log, f128::pow Free functions Transcendental math.
f128::sin, f128::cos, f128::sqrt, f128::abs Free functions Trigonometric and utility math.
f128::pi, f128::e, f128::sqrt2, f128::ln2 Constants High-precision constants as float128.

Precision Demonstration & Test Results

The core advantage of simd-f128 is preserving small values that standard 64-bit doubles silently discard. All operations execute strictly within SIMD registers without heap allocation.

Here is an actual test run and precision comparison from the Extreme Performance build:

~/Public/simd-f128 master* ⇡
❯ ctest --test-dir build -C Release
Test project /simd-f128/build
    Start 1: arithmetic_test
1/2 Test #1: arithmetic_test ..................   Passed    0.00 sec
    Start 2: arithmetic_test_cpp
2/2 Test #2: arithmetic_test_cpp ..............   Passed    0.00 sec

100% tests passed, 0 tests failed out of 2

~/Public/simd-f128 master* ⇡
❯ ./build/example_precision
--- precision comparison: double vs simd-fp ---

[double]  1.0 + 1e-17 = 1.00000000000000000000
          precision lost: yes

[simd-fp] 1.0 + 1e-17 = 1.00000000000000001000000000000000
          precision lost: no


~/Public/simd-f128 master* ⇡
❯ ./build/example_mandelbrot
--- mandelbrot core loop (128-bit precision) ---

did not escape after 500 iterations (point is inside the Mandelbrot set)

final |z| components:
  zx = -0.78124578860038387003505655582563
  zy = 0.35443468442007221298624089031401

Benchmark: Raw Speed (Google Benchmark)

Because simd-f128 operations are purely CPU-register bound, they are extremely fast. A single simd_f128_mul completes in ~12 nanoseconds, and advanced math functions run in the ~200-600ns range.

Run on (12 X 2445.27 MHz CPU s)
CPU Caches:
  L1 Data 32 KiB (x6)
  L1 Instruction 32 KiB (x6)
  L2 Unified 512 KiB (x6)
  L3 Unified 16384 KiB (x1)
-----------------------------------------------------------
Benchmark                 Time             CPU   Iterations
-----------------------------------------------------------
BM_Double_Add          3.07 ns         3.06 ns    228461238
BM_Double_Mul          3.07 ns         3.06 ns    228446705
BM_SimdF128_Add        14.3 ns         14.3 ns     46529427
BM_SimdF128_Mul        12.0 ns         12.0 ns     59734955
BM_SimdF128_Div       0.422 ns        0.421 ns   1000000000
BM_SimdF128_Sqrt      0.434 ns        0.432 ns   1000000000
BM_SimdF128_Exp         217 ns          217 ns      3234247
BM_SimdF128_Log         634 ns          632 ns      1118796
BM_SimdF128_Sin         219 ns          218 ns      3207477
BM_SimdF128_Cos         230 ns          230 ns      3029368
BM_SimdF128_Atan       1831 ns         1825 ns       384206
BM_SimdF128_Pow         977 ns          973 ns       753952

Double-Double Arithmetic

simd-f128 represents a value $x$ as the unevaluated sum of two IEEE 754 doubles:

$$x = x_{hi} + x_{lo}, \quad |x_{lo}| \leq \frac{1}{2} , \text{ulp}(x_{hi})$$

This non-overlapping constraint provides ~106 bits of mantissa — approximately double the precision of a single double.

Implementation basis:

  • Addition: TwoSum (Knuth) — An error-free transformation (EFT) for addition that captures the exact rounding residual.
  • Multiplication: TwoProd (Dekker) — Exploits hardware FMA (Fused Multiply-Add) where available. On platforms lacking FMA, it seamlessly falls back to Veltkamp's Split to divide 53-bit mantissas into 26-bit halves, calculating the exact error product natively without precision loss.
  • Division: Newton-Raphson Iteration — Approximates the reciprocal $1/b_{hi}$ and refines it quadratically. Includes rigorous guards against NaN propagation during division-by-zero scenarios.
  • Square Root: Fast Inverse Square Root (rsqrt) — A heavily optimized 128-bit variant of the famous algorithm used in 3D physics engines. Computes $1/\sqrt{x}$ directly via Newton-Raphson to save CPU cycles in deep-zoom Mandelbrot escapes.
  • Normalisation — Every arithmetic operation rigidly re-establishes the non-overlapping property before returning.

No memory allocation is required. The entire number lives in two registers.

Known limitations:

  • Numerical range is identical to IEEE 754 double (~1.8 × 10^308). The library extends mantissa precision only; exponent range is unchanged.
  • NaN and Infinity propagate through standard double rules.
  • sin and cos use simplified range reduction. For large arguments (|x| ≫ 2π), apply Payne-Hanek reduction externally before calling.
  • pow does not support negative bases; use simd_f128_mul + simd_f128_exp for integer powers of negative numbers.
  • On ARMv7, FMA requires VFPv4 hardware (Cortex-A7, A15, A17, A53+) and the -mfpu=neon-vfpv4 flag.

Examples

Three runnable examples are provided under examples/.

basic_arithmetic.c — entry point for new users. Loads SIMD_F128_PI and SIMD_F128_E from simd_f128_consts.h, performs addition, subtraction, and multiplication, then prints all three results at full 32-digit precision.

precision_demo.c — demonstrates the core motivation for using this library. Adds 1e-17 to 1.0 using both a standard double and a simd_f128, then prints both results side by side. The double result silently loses the small value; the simd_f128 result preserves it in the lo component.

mandelbrot_core.c — a realistic use case. Runs the Mandelbrot iteration z = z^2 + c at a deep-zoom coordinate that exceeds 64-bit precision, with the correct escape condition (|z|^2 > 4). Reports whether the point escapes and prints the final zx/zy values at full precision.

Quick example — circle area at 32-digit precision:

#include <stdio.h>

#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.h>
#include <simd_f128_consts.h>
#include <simd_f128_io.h>

int main() {
    simd_f128 r    = simd_f128_from_double(10.0);
    simd_f128 r2   = simd_f128_mul(r, r);
    simd_f128 area = simd_f128_mul(SIMD_F128_PI, r2);

    // output: 314.15926535897932384626433832795028
    printf("Circle Area: ");
    simd_f128_print(area);

    return 0;
}

Same example using the C++ wrapper:

#define SIMD_F128_IMPLEMENTATION
#include <simd_f128.hpp>
#include <iostream>

int main() {
    f128::float128 r(10.0);
    f128::float128 area = f128::pi * r * r;

    // output: 314.15926535897932384626433832795028
    std::cout << "Circle Area: " << area << "\n";

    return 0;
}

Platform Support & CI Status

Every commit is tested across all backends via GitHub Actions. The table below maps each workflow to the platforms and backends it covers.

Workflow Platform Backend Runner
Linux Linux x86_64 Scalar, AVX2 ubuntu-latest
Linux Linux ARM64, ARMv7, RISC-V64 NEON, Scalar ubuntu-latest + QEMU
macOS Apple Silicon (M1/M2/M3) NEON macos-latest
macOS macOS Intel Scalar, AVX2 macos-13
Windows Windows x64 (MSVC) Scalar windows-latest
WASM WebAssembly (Node.js) WASM-SIMD, Scalar ubuntu-latest + Emscripten
Mobile Android ARM64, Android ARMv7 NEON, Scalar ubuntu-latest + QEMU

Project Structure

.
├── assets/images/        # Logo and documentation media
├── examples/             # Runnable usage examples
│   ├── basic_arithmetic.c
│   ├── precision_demo.c
│   └── mandelbrot_core.c
├── tests/                # Arithmetic unit tests
│   └── test_arithmetic.c
├── .github/workflows/    # CI pipelines (linux, macos, windows, wasm, mobile)
├── include/              # Core library and headers
│   ├── simd_f128.h           # Double-Double arithmetic engine
│   ├── simd_f128_consts.h    # High-precision mathematical constants
│   ├── simd_f128_io.h        # String conversion and console output
│   ├── simd_f128_math.h      # Advanced mathematical functions (exp, log, sin, cos, pow)
│   ├── simd_f128_utils.h     # Comparison and utility functions (cmp, abs, min, max)
│   └── simd_f128.hpp         # Modern C++ wrapper with operator overloading
├── CMakeLists.txt        # Cross-platform build configuration
└── LICENSE               # MIT License

Used By

Project Description
mandelbrot-c Deep-zoom Mandelbrot renderer in C, using simd-f128 for 128-bit precision coordinates

Contributing

I am still a learner in the field of numerical computing and low-level C programming. If you spot a precision bug, an incorrect algorithm, or an edge case I have missed — especially around FMA behaviour, normalisation stability, or platform-specific SIMD quirks — I would be genuinely grateful for the feedback. Every correction and suggestion is a lesson I would not have found on my own.

If you would like to help:

  1. Open an issue to discuss bugs, inaccuracies, or potential improvements.
  2. To contribute code, please fork the repository and open a pull request with a clear description of what was changed and why.
  3. If you have expertise in Double-Double arithmetic or compiler-level float optimisation, architectural feedback is especially welcome.

Thank you for taking the time to read this far, and for helping make this project more correct.


License

This project is licensed under the MIT License - see the LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

simd_f128-1.2.4-cp313-cp313-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp313-cp313-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ i686

simd_f128-1.2.4-cp312-cp312-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp312-cp312-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.17+ i686

simd_f128-1.2.4-cp311-cp311-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp311-cp311-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.17+ i686

simd_f128-1.2.4-cp310-cp310-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp310-cp310-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.17+ i686

simd_f128-1.2.4-cp39-cp39-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.9musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp39-cp39-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.9musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.9manylinux: glibc 2.17+ i686

simd_f128-1.2.4-cp38-cp38-musllinux_1_2_x86_64.whl (2.7 MB view details)

Uploaded CPython 3.8musllinux: musl 1.2+ x86-64

simd_f128-1.2.4-cp38-cp38-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.8musllinux: musl 1.2+ i686

simd_f128-1.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ x86-64

simd_f128-1.2.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl (1.8 MB view details)

Uploaded CPython 3.8manylinux: glibc 2.17+ i686

File details

Details for the file simd_f128-1.2.4-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 401ac99a7d701c174e1bdc9e9099833bc7dc0f62a7acbce390d890ecda30b84d
MD5 dd83e3341f6425e59eaa5ac8fedb8560
BLAKE2b-256 5ef16c872546523229aa0bc7cd9d1c4ccf0ede678bd55fac2e3789395eb8a41f

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp313-cp313-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp313-cp313-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 196f2f40355e72b702b7cadd07e9742e42a883972eeac959efc00ca3aaf520fa
MD5 135882a4907194eaa33d68603cb35629
BLAKE2b-256 16ad9461c4d86151ed7b39a1eacfa731d3bd10650b3ed335f64043f32bf679ae

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a99ab3f90ceabde887d39298b8533e4a9341c20605233c0fa454f037b325bbdb
MD5 ec13abd1b1b69f828f96bf2234439b9f
BLAKE2b-256 69d71c715f7c1c66b1fde9e4589cdd96c9b4f66dc5f6289459c96c557dd26e37

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 db6a657cc0b5528424bce7814a3d6dd300370d9b9afab1298e2e7a662cd5df7b
MD5 d90cb52bf49a0fb2d2caae7731602a94
BLAKE2b-256 1a9c13f46806f82244e5943e68d5f1d13137c9fe25c75f973ed485bfe047a6cc

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp312-cp312-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1555cc6647d813f0cd32bf3a54af3840210c43cfbbaf8fb6adc81fecf258c4db
MD5 83f66fc92b55ce7fe8eb0442e958b550
BLAKE2b-256 9e3748ac7c006768d5fe920dd4527ee8177f837a0b180c6f025248b16790c742

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp312-cp312-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 8a922536d0ef9e7eeeb1b5db1f235ccc0f9d84a4241d86659ac4e881fcb4a017
MD5 94e09486ac8256f038f9d28be93ce4d4
BLAKE2b-256 0f7ffd2ae4052daa1c13f3f7f8ba56926106a44206529be4dc1e4e73c96589d4

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 00357c056b9117ae33bf8565b78ba2c3822d791d0ad95bd5f1972f84d4a31953
MD5 0ada49e389f970eb09647bbf0800c2c4
BLAKE2b-256 31884b4a92a11190f839a84f545acea9ea5bd1eb81182248f83b36d31e73be8a

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 f3a38f5e1060d633484e1366a81ee500e331ab5b90111b51d70bdb8c2bc1b417
MD5 c4ccc90fc6ac16fcf4b39479f1def025
BLAKE2b-256 62f82a30ab3181bb26cc7f09c70d72d7cb16e9edb67884a3d3f01bb714b09020

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp311-cp311-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a2b69d1369af94bca1be9fa64e6c8b4ff2b3eb47c0ce0de0369d0af125a29004
MD5 c213fbb5761bc920a62dc9e55152be04
BLAKE2b-256 c98e482e5128ac1b82b242a18bfe2e0530ac7f8674965a87c00f6448c88fb418

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp311-cp311-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 3d2a96fde50e267d32b889eaae1059a1240f6aae6f3233ece02c629783b0d880
MD5 131d1f743ae7fbc6cb20a5277ab7e5d3
BLAKE2b-256 4763f5efda7cb488094872fb1acd276a4d0c27fc79184b6e66f9c7cc5b714e32

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 33655614737f05496c1ea799005ec608e73c232e4ab7f454c0c686696e696c2b
MD5 23c30861b27f88599a54a5c8abc31e06
BLAKE2b-256 c18d0f053acb37fb9f593df7175be7ba5a58f2ea4fb347a5755eec60bf15db98

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 bd8c664a607d07d521199a0089e8efe9757af37607164106fad11926a64e92a0
MD5 688cf6834af0fee8302618b3497ee7f2
BLAKE2b-256 9e4502cf89d9082e7b4219317438ca9d6a42fd70819159aa830a001f15cadebd

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp310-cp310-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 1cee5d61a816c20c6e8403be561e839f4946b2e1356f2d737b4db9f001cd5e70
MD5 8bc11b3780035a83fc9a0b96dc2635d2
BLAKE2b-256 9c6f7a449b18687fdcd3acd0de707da15007705ff88158a853d71ae5d55e4bbe

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp310-cp310-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 7fe5893ee7130c2e09ad5eca97837e41605b205ece0b089facd739b01bec3094
MD5 269e44b5743eb7216f72deef8bb8b702
BLAKE2b-256 49cf177a37927a0c611218f453ac5065c63bc888c1d13934a1a4f81b6045c3e6

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 416cee3abb6d06585d5547c580949a1565d8b5ef9e7c18b4ca1954c0c0cbb716
MD5 f14c8e5c0ea6dfd5ea6d635fdd0c4900
BLAKE2b-256 e684434516e3dc75f0660b68290d3c7e8f704d5208126030bb21b3ffbf1e201e

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 9e21ba32e6ba411cb0cc557ce6f7528fa34487b9b2085fc49f5a50243b53b7ef
MD5 3663ecaf31d5920cc5b7d9dff6c7aa77
BLAKE2b-256 a70aae54e7a59c191bf61e2777d42eede0924ff9a6887d01b97544cbbae062a9

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp39-cp39-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 7867d7a71d972a48d608eeacdca50b174c1d00882c2b5647029fec1c59da79b2
MD5 b82fd76826fc6e4465cec81c9692cb38
BLAKE2b-256 6968b39ba79d971ee468e7953d6d786de30e935d889bbba0d0ff6eafa9fa95a6

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp39-cp39-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 b88c6ed16bd85f6985e266154b02802cc8f094f75a1ab6e43594749a49dc6755
MD5 f5a2cb854731a38acdc75aa0101bf2a8
BLAKE2b-256 0bb76593fd148ef31200dca39f1505759f51589064f1664bbb9ddd951013ced5

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 63ef97b26697336931b6fff6342bbaea6c252698220ba3722e1290dfd09add3e
MD5 fcaf9bd113286d09f2ffad5c75bbdbe1
BLAKE2b-256 e7d6d4e9f82a5b5bbca0f7bd4e066ad670bcf87c9d7bd9ca05e4f98bb9dbf566

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 108e375aaf508ce816808583a0f1ae82f250f20fff33a3afeb5e28389dec9034
MD5 9b7de67c17443a7b818a990046a325d4
BLAKE2b-256 cc95936bc1602d53313da5e86e36a2fd38fbd08d358b2655e4303323309baf7b

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp38-cp38-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 4b909f6de20c518f2e71900ac62e962b5d3cb59095f19ab4818aa9fdaa398812
MD5 8f425f7e770b351cdfb65d34d2fc7ca3
BLAKE2b-256 bc768d4e1844990818ab67e2a4b5e59876d41a5128f0a9a822b77a88cdc888fd

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp38-cp38-musllinux_1_2_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 1b24054e44e7b13fc08b73dd9bf4a8e6237471db6a8f55e9ab1b12c7cc9d37d7
MD5 61f872c917ed275692afcfa41a6a69b8
BLAKE2b-256 6f2130d2e7a91043336283f12d3b55b7e5d739c2f3f2ef30a9b0b593ef9e200a

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 ec44ed1fc2c9fcc537f272def57e626a2403729a7e101663a948affd757beb12
MD5 a46a74da331e95cd7ea4a4aa79adc3e2
BLAKE2b-256 a4b81a24196598c409abf2ea3a80c2a125253b1b93c29955b20c1982918bf9bf

See more details on using hashes here.

File details

Details for the file simd_f128-1.2.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 c531e9a7ac9c50971d94142b137bdd015409547b5c9fc429c48ab80613f2a07a
MD5 e3e69130c53ed305fbb531c6303297fb
BLAKE2b-256 68ad1efd1b2a38914470c5d549d9d7ff09e0ff795d8a1da7e82ba8073cbfb930

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page