Header-only C/C++ library for deterministic fixed-point arithmetic.
Version 0.1.1 — Changelog
- Multiple Q formats: Q1.15, Q16.16, Q8.24, Q32.32, Q64.64
- Decimal NUMERIC(P,S) types: 8 predefined types (n9_2 through n19_6), C++ template
fx::decimal<P,S,R> - String conversion:
from_string/to_stringwith overflow detection - Rescale: runtime precision conversion between different scales
- 6 rounding modes: HALF_UP (default), HALF_EVEN, HALF_DOWN, TRUNCATE, CEILING, FLOOR
- Generic C++ template:
fx::fixed_point<BaseType, IntBits, FracBits> - Complete math library: sqrt, sin, cos, atan2, exp, log, pow
- Saturating arithmetic: optional overflow clamping
- SIMD batch operations: SSE2/AVX2/NEON auto-detection
- Zero dependencies: header-only, C99/C++14 compatible
- Cross-platform: Linux, macOS, Windows (GCC, Clang, MSVC)
#include "fx/fx.h"
fx_q16 a = fx_q16_from_float(3.14f);
fx_q16 b = fx_q16_from_float(2.0f);
fx_q16 c = fx_q16_mul(a, b);
printf("result: %f\n", fx_q16_to_float(c));#include "fx/fx.hpp"
fx::q16 a = fx::q16::from_float(3.14f);
fx::q16 b = fx::q16::from_float(2.0f);
fx::q16 c = a * b;
std::cout << c.to_float() << std::endl;add_subdirectory(integer)
target_link_libraries(my_app PRIVATE fx::fx)include(FetchContent)
FetchContent_Declare(fx
GIT_REPOSITORY https://github.com/user/integer.git
GIT_TAG v0.1.1
)
FetchContent_MakeAvailable(fx)Copy include/fx/ into your project and add to include path.
| Type | Format | Range | Precision |
|---|---|---|---|
fx_q1_15 |
Q1.15 | [-1, 1) | 3.05e-5 |
fx_q16 |
Q16.16 | [-32768, 32768) | 1.53e-5 |
fx_q8_24 |
Q8.24 | [-128, 128) | 5.96e-8 |
fx_q32_32 |
Q32.32 | [-2^31, 2^31) | 2.33e-10 |
fx_q64_64 |
Q64.64 | [-2^63, 2^63) | 5.42e-20 |
fx::q1_15, fx::q16, fx::q8_24, fx::q32_32
Note:
fx_q64_64uses a custom 128-bit struct (hi+lo) and is C-only.
| Header | Description |
|---|---|
fx/fx.h |
C aggregate header (all Q-format types) |
fx/fx.hpp |
C++ aggregate header |
fx/decimal/n9_2.h |
Decimal NUMERIC(9,2) C API |
fx/decimal/n18_2.h |
Decimal NUMERIC(18,2) C API |
fx/decimal/n18_4.h |
Decimal NUMERIC(18,4) C API |
fx/decimal/n18_6.h |
Decimal NUMERIC(18,6) C API |
fx/decimal/n18_8.h |
Decimal NUMERIC(18,8) C API |
fx/decimal/n19_2.h |
Decimal NUMERIC(19,2) C API |
fx/decimal/n19_4.h |
Decimal NUMERIC(19,4) C API |
fx/decimal/n19_6.h |
Decimal NUMERIC(19,6) C API |
fx/decimal/decimal_math.h |
Decimal math functions (C aggregate: sqrt, lerp) |
fx/decimal/decimal_math.hpp |
Decimal math free functions (C++: fx::sqrt, fx::lerp) |
fx/decimal/decimal.hpp |
Decimal C++ template and aliases |
fx/simd/simd_dec_ops.h |
SIMD batch operations for decimal types (add_array, sub_array) |
| Type | Format | Range | Precision |
|---|---|---|---|
fx_dec_n9_2 |
NUMERIC(9,2) | ±9999999.99 | 0.01 |
fx_dec_n18_2 |
NUMERIC(18,2) | ±9999999999999999.99 | 0.01 |
fx_dec_n18_4 |
NUMERIC(18,4) | ±99999999999999.9999 | 0.0001 |
fx_dec_n18_6 |
NUMERIC(18,6) | ±999999999999.999999 | 0.000001 |
fx_dec_n18_8 |
NUMERIC(18,8) | ±9999999999.99999999 | 0.00000001 |
fx_dec_n19_2 |
NUMERIC(19,2) | ±10^17-0.01 | 0.01 |
fx_dec_n19_4 |
NUMERIC(19,4) | ±10^15-0.0001 | 0.0001 |
fx_dec_n19_6 |
NUMERIC(19,6) | ±10^13-0.000001 | 0.000001 |
fx::decimal<Precision, Scale, Round> template with predefined aliases:
fx::dec9_2, fx::dec9_4, fx::dec9_6,
fx::dec18_2, fx::dec18_4, fx::dec18_6, fx::dec18_8,
fx::dec19_2, fx::dec19_4, fx::dec19_6.
dec9_4anddec9_6are C++-only (no C API header); all other aliases have corresponding C types (fx_dec_n*_*) in their respective headers.
Rounding modes: fx::rounding_mode::HALF_UP (default), HALF_EVEN, HALF_DOWN, TRUNCATE, CEILING, FLOOR.
Q-format: sqrt, sin, cos, atan2, exp, log, pow, abs, lerp, min, max, clamp
Decimal math (available for all decimal types):
| Function | Description | C API | C++ member | C++ free |
|---|---|---|---|---|
sqrt |
Square root (Newton-Raphson). Negative input returns zero. | fx_dec_*_sqrt(x) |
x.sqrt() |
fx::sqrt(x) |
lerp |
Linear interpolation: a + (b - a) * t |
fx_dec_*_lerp(a, b, t) |
a.lerp(b, t) |
fx::lerp(a, b, t) |
Header: fx/decimal/decimal_math.h (C), fx/decimal/decimal_math.hpp (C++ free functions)
C: fx_q16_add_sat, fx_q16_sub_sat, fx_q16_mul_sat, fx_q16_div_sat
C++: a.add_sat(b), a.sub_sat(b), a.mul_sat(b), a.div_sat(b)
Q-format: fx_q16_add_array, fx_q16_mul_array, fx_q16_sqrt_array, fx_q16_sin_array, fx_q16_cos_array
Decimal batch operations (C API, via fx/simd/simd_dec_ops.h):
| Function | Description |
|---|---|
fx_dec_*_add_array(a, b, out, count) |
Batch addition. P<=18 types use SSE2 2-wide int64; P=19 types use scalar fallback. |
fx_dec_*_sub_array(a, b, out, count) |
Batch subtraction. Same SIMD strategy. |
Available for all decimal types: fx_dec_n9_2, fx_dec_n18_2, fx_dec_n18_4, fx_dec_n18_6, fx_dec_n18_8, fx_dec_n19_2, fx_dec_n19_4, fx_dec_n19_6.
#include "fx/decimal/n18_4.h"
fx_dec_n18_4 x = fx_dec_n18_4_from_double(2.0);
fx_dec_n18_4 s = fx_dec_n18_4_sqrt(x);
printf("sqrt(2.0) = %f\n", fx_dec_n18_4_to_double(s));
fx_dec_n18_4 a = fx_dec_n18_4_from_double(10.0);
fx_dec_n18_4 b = fx_dec_n18_4_from_double(20.0);
fx_dec_n18_4 t = fx_dec_n18_4_from_double(0.25);
fx_dec_n18_4 v = fx_dec_n18_4_lerp(a, b, t);
printf("lerp(10, 20, 0.25) = %f\n", fx_dec_n18_4_to_double(v));#include "fx/decimal/decimal_math.hpp"
fx::dec18_4 x = fx::dec18_4::from_double(2.0);
fx::dec18_4 s = x.sqrt(); // member function
fx::dec18_4 s2 = fx::sqrt(x); // free function
fx::dec18_4 a = fx::dec18_4::from_double(10.0);
fx::dec18_4 b = fx::dec18_4::from_double(20.0);
fx::dec18_4 t = fx::dec18_4::from_double(0.25);
fx::dec18_4 v = a.lerp(b, t); // member function
fx::dec18_4 v2 = fx::lerp(a, b, t); // free functioncmake -B build -DBUILD_TESTS=ON
cmake --build build
ctest --test-dir buildcmake -B build -DBUILD_EXAMPLES=ON
cmake --build build| Standard | Status |
|---|---|
| C99 | Minimum required (C API) |
| C++14 | Minimum required (C++ API, full constexpr support) |
| C++11 | Compiles but constexpr degrades to inline (set cxx_std_11 in CMake if needed) |
Note: The C++ API uses
constexpron most member functions and helpers. On C++14+ these evaluate at compile time. On C++11 they compile as ordinaryinlinefunctions — fully functional, but without compile-time evaluation.
| Platform | Status |
|---|---|
| GCC/Clang (Linux/macOS) | All types including n19_* (__int128) |
| MSVC x64 | All types except n19_* (no _int128 support; use n18* instead) |
| MSVC x86 | Scalar fallback path only (SSE2 detection fixed in v0.1.1) |
Note: n19_* types (
fx_dec_n19_2,fx_dec_n19_4,fx_dec_n19_6,fx::dec19_*) require 128-bit integer support and are available on GCC/Clang only. On MSVC, use the equivalent n18_* types which achieve 128-bit intermediate precision via_mul128/_umul128intrinsics.
BSD 3-Clause