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.0-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.0-cp313-cp313-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.13musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-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.0-cp312-cp312-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.12musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-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.0-cp311-cp311-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.11musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-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.0-cp310-cp310-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.10musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-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.0-cp39-cp39-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.9musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-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.0-cp38-cp38-musllinux_1_2_i686.whl (2.8 MB view details)

Uploaded CPython 3.8musllinux: musl 1.2+ i686

simd_f128-1.2.0-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.0-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.0-cp313-cp313-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp313-cp313-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 a5ce5716f59a3b1d351202e8b601bbb495b12d55ddf56c89d453b58f7b1fc442
MD5 f8849ecbe5079510371cdcf2d3ae78dd
BLAKE2b-256 8ec29b74a8eff0cca6ebfd8253915f6e715e5bb71f02adbb6c2397f0ff4f6ef0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp313-cp313-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 0dfe5e3424c6c1b12eb817fde04c823a373fa55090b196c04f527146cd8a9a30
MD5 81e52a013f7dc81572557a30df7ebc6c
BLAKE2b-256 7a6da33cd204e0cd58b14a9025b15159f593cd14a52e416cd0411bb2a915c27b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 6f8125ae95d11df35abfdf34bc35def960b16b1b223c2f4048a690d139e7b6d6
MD5 022144009a42b3cdbada12a736ce7d56
BLAKE2b-256 e6a54f172d78fba9fc5850f4963b1dd24d3e7843ced1aace9ee7aeea1df47628

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp313-cp313-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 8a2b7cdbb5e00145e649bb8222cb8c99da562ed0e6e8856f7cc265ed688a258e
MD5 f5fab88e7f7e67d6a015ba3396795274
BLAKE2b-256 46819385926b712f6745c77c59144599a59f095e661daae38c581c95f5431247

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp312-cp312-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 112e90f28b256138b3cca34bd4e27369e3b15e2359f7451bd583310a433d1b9e
MD5 e7df022ead8a83adfa77dfac179d6573
BLAKE2b-256 a7d49c93b596145664f58d785be38e1869ceb7dddf1a090f1ccfc413d6df8853

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp312-cp312-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 77d72c048c3820cb74291135188122d4ac203b2ca29fc52bb5788d42b88cde57
MD5 aa54a5497d02665c94fa10f44f236dce
BLAKE2b-256 ec0858adc10c67caad76a46fd666b5d9fda9be30f4b3deeebadfb9eb94b086e1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 59e649be88bc5a9773c2f0b6e2b95925b1cb2a46cb4256cdf0d0fdf4026f69b9
MD5 e1ced3facc3c2b395cacd1d31788f1fa
BLAKE2b-256 aca756ce58fa916a38ed22f4c093d9ca3f7cb9399c79c2003ede36e89471e8be

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 e1ae2f49832e43ee151c809a0bb60d3942588eacb99287325519c6378dbba79b
MD5 d6c617020ac3ada66daef6d35d19ccb5
BLAKE2b-256 7c91c6757414a4c2e988adb54ae112ee4ffe3b675278aec6161e578f6f7ffd85

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp311-cp311-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 b90dc23f61f90d4d998ce4ae1a63d32c50371cda9d8bc44bdb51f2d5e8c2d5bc
MD5 1484f5382fa9746185ae842359d28bbe
BLAKE2b-256 b4b88b0143c77420f0ccf084366e9f7881fd3f85d2ae5bb9c37c40dd1cb68347

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp311-cp311-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 7edd39548faa6b03050ca3cdfe39e489f8681f223b61b6a17f7a14d44f510dad
MD5 c1f12d9d90fcbb36ccb3591d96ae89bf
BLAKE2b-256 776cf2453a9cf942aa141d14f63850ef59883b27b2dd913a21b8ab6dfd973459

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 69811f6bb035fbe10db899e37a6a0d42cc23ed6af1058848a08cc7cac36d616b
MD5 7b2020a52bf256cb162e7ccb813ae5c5
BLAKE2b-256 10e3c1753feaaf91b3948a64d88202f803d70a773d388b4b442820b503cccac0

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 42d373fae0a45e99ca40be67f652c561ae43d7877d941dadbe5e122cfb1c4c60
MD5 a380eac3b53500f4c0d0d4bcd494469e
BLAKE2b-256 e5a601504870df305967f6aebbdaa5022af86c9e17a8c1c00080b6d3a1c61081

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp310-cp310-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 36823099f0a7488ad5a26886a083fecc29f4ee0dd10f73cb379af6605d603ebe
MD5 c9eb191f87f41bd60a373acca7b5cb0b
BLAKE2b-256 59fd92f9f162e4521827150b570747cd295e86727108893620857308e9bb650f

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp310-cp310-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 77851c7cad9c3c69fda5522eea65162003793aafff3d2328ca40831d0fea51ae
MD5 ff6e89759a1a707f4d4643817289dd95
BLAKE2b-256 260c16358477a62ac41e3fdf5fd58a2a8de442d240febdf3cbfb98329d38a828

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 aef8d280a6ffb6a6b47ce4951e5c2787371c291c9888b4865b36660affaaa63c
MD5 2bc84f476591004554af338d63ad2991
BLAKE2b-256 88c5521010fe8a5fb219187e1e7ad4238118bb3b5d012abd73cc44fdba4823dd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 18f4747d54e77d6baafa0bd0afeac6bfacca10d9b8914da55fa7edabd53afe71
MD5 e493636877eff47a3cebc0268b4d73d8
BLAKE2b-256 6fd4b14f5240673ea8c499a67217b3b212dfa7972c1024f6c7a74092d9322b87

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp39-cp39-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 5d042ce817c1d45bc729cde9b0fbea07df85758a63aad6aa8d3c0f1d56dff1f4
MD5 64fe8d139f976ad7f864be05de6c1743
BLAKE2b-256 267d34d0596e05a0510e4ba7c1fa47628c529fecb332cb42c9843144d1b26f16

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp39-cp39-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 4ea496359ddd794b42df0ea2cfb897bb988164929e7d25d4894abe439728d125
MD5 81e333c67796223ed2d30b19a8b56dc6
BLAKE2b-256 0c22160d15712c7161d653562b7157f478b343dd8736def93ddd902b946e463a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 eaa4e6e1e2cd1a387ceba39bfb4a052905e62d7e23c3ca7d97481227da77163b
MD5 4e53916b5557f4d449203134df379b2f
BLAKE2b-256 1471437a965c110e9845cf48f2fd408abafd760789babdc9739198c84257d685

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 741d57fc265e376138ec3b3d0bb3d98c437b1a5d1fb508712239c4fa6fd0d7f2
MD5 20ce4742909e9dcc5b418c0b2ae0d59b
BLAKE2b-256 7c82cc4317fc5959ec7a538e3f03c458c221f795193d74e718761769ad308189

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp38-cp38-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 46ec75525b4f47953da921fb1ef6ed5a27f47031e95c23b83d040cab338f1ea8
MD5 339ca65bc26214cce85f0c2da53ea948
BLAKE2b-256 31e9ed37a387e50ca1612c3dd19d1c7d77289846f09ed00df57273895c285d91

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp38-cp38-musllinux_1_2_i686.whl
Algorithm Hash digest
SHA256 213b973446c55d5d551cf7a229d32988b50f9d94806bf5ea9f0058fe112a306f
MD5 62eb111d5b6609d4f5b84842116f7a9d
BLAKE2b-256 4a2b287aacf474b8e41b96d80d2de20065f1b9d09dd329e17cb791a39e095b57

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 2941b88d6f0a63f22165d430dde58b5742de2b16510b94427b91bb2179ab8830
MD5 f0ed23c50f5a455f571419b656e33bf7
BLAKE2b-256 280771fe76b1937f249d8b4045a4fd43c22a49c671b092f59862aaa6e31db5cf

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for simd_f128-1.2.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 afc06bc76057893d3603daf0d53d7bf38ae139df35c86584797e51a796765dce
MD5 17f500893f9fe1acbf3d2bbfce06d766
BLAKE2b-256 cd5acc159e2ba2c03f0f7fb57ed7226b4384950a3e24d0efd7da9a7aa224e0bc

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