Skip to content

tgergo1/limitless

Limitless

CI Coverage Release Latest release License Coverage (codecov) Open issues Open PRs Last commit GitHub stars C C++ Platforms CMake Conan vcpkg Status

Single-header exact big numbers for c and c++. It stores exact integers and exact fractions (a/b) and grows until memory runs out.

Current line: experimental, version 0.1.0.

What is in this repo

  • limitless.h: C API + implementation (#define LIMITLESS_IMPLEMENTATION in one TU)
  • limitless.hpp: C++ wrapper (limitless::number) with operators and RAII on top of the C API
  • tests/: baseline tests, generated matrix tests, stress tests, CI wrappers
    • API completeness + alias/failure-atomic tests
    • parser fuzz + valid roundtrip stress
    • C++ thread behavior tests
    • differential checks against a python fractions.Fraction reference
  • packaging metadata for CMake, pkg-config, Conan, and vcpkg overlay port

current version is tracked in LIMITLESS_VERSION.txt and exposed in limitless.h:

  • LIMITLESS_VERSION_MAJOR
  • LIMITLESS_VERSION_MINOR
  • LIMITLESS_VERSION_PATCH
  • LIMITLESS_VERSION_STRING

Minimal use

C

#define LIMITLESS_IMPLEMENTATION
#include "limitless.h"

int main(void) {
  limitless_ctx ctx;
  limitless_number x, y;
  char buf[64];

  if (limitless_ctx_init_default(&ctx) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &x) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &y) != LIMITLESS_OK) return 1;

  limitless_number_from_str(&ctx, &x, "7");
  limitless_number_from_str(&ctx, &y, "3");
  limitless_number_div(&ctx, &x, &x, &y);
  limitless_number_to_str(&ctx, &x, buf, sizeof(buf), NULL);

  limitless_number_clear(&ctx, &x);
  limitless_number_clear(&ctx, &y);
  return 0;
}

C++

#define LIMITLESS_IMPLEMENTATION
#include "limitless.hpp"

int main() {
  int a = 3;
  limitless::number x = 33424234;
  limitless::number y = (x + a) / 2.3f;
  return y.str() == "140191410946048/9646899" ? 0 : 1;
}

Legacy global wrapper names are currently bridged for compatibility. Prefer limitless::number and limitless::limitless_cpp_*. Strict mode is available via #define LIMITLESS_CPP_LEGACY_API 0 before including limitless.hpp. Migration details: docs/MIGRATION_CPP_NAMESPACE.md.

When this is practical

limitless is useful when exactness matters more than raw speed:

  • exact fractions in calculators, symbolic tools, or education projects
  • big integer math that can exceed 64-bit limits (IDs, counters, crypto exercises)
  • deterministic parse/compute/format pipelines where float rounding is not acceptable
  • portability-focused C/C++ projects that want a small integration surface (single header)

Less practical cases:

  • heavy numeric workloads that are fine with IEEE floating point
  • tight real-time loops where big-integer allocation cost is too high
  • scientific/ML workloads that are already built around vectorized float math

More examples

C: parse, exact divide, print

#define LIMITLESS_IMPLEMENTATION
#include "limitless.h"

int main(void) {
  limitless_ctx ctx;
  limitless_number a, b, out;
  char buf[128];

  if (limitless_ctx_init_default(&ctx) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &a) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &b) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &out) != LIMITLESS_OK) return 1;

  limitless_number_from_str(&ctx, &a, "123456789012345678901234567890");
  limitless_number_from_str(&ctx, &b, "97");
  limitless_number_div(&ctx, &out, &a, &b);   /* exact rational if needed */
  limitless_number_to_str(&ctx, &out, buf, sizeof(buf), NULL);

  limitless_number_clear(&ctx, &a);
  limitless_number_clear(&ctx, &b);
  limitless_number_clear(&ctx, &out);
  return 0;
}

C: exact float import and integer export

#define LIMITLESS_IMPLEMENTATION
#include "limitless.h"

int main(void) {
  limitless_ctx ctx;
  limitless_number n;
  limitless_i64 out = 0;

  if (limitless_ctx_init_default(&ctx) != LIMITLESS_OK) return 1;
  if (limitless_number_init(&ctx, &n) != LIMITLESS_OK) return 1;

  /* 0.5 is represented exactly as 1/2 */
  if (limitless_number_from_double_exact(&ctx, &n, 0.5) != LIMITLESS_OK) return 1;

  /* range-checked integer export */
  if (limitless_number_to_i64(&ctx, &n, &out) == LIMITLESS_ERANGE) {
    /* not an integer or out of range */
  }

  limitless_number_clear(&ctx, &n);
  return 0;
}

C: modular exponentiation (integer-only API)

#define LIMITLESS_IMPLEMENTATION
#include "limitless.h"

int main(void) {
  limitless_ctx ctx;
  limitless_number base, mod, out;
  char buf[64];

  limitless_ctx_init_default(&ctx);
  limitless_number_init(&ctx, &base);
  limitless_number_init(&ctx, &mod);
  limitless_number_init(&ctx, &out);

  limitless_number_from_u64(&ctx, &base, 4);
  limitless_number_from_u64(&ctx, &mod, 497);
  limitless_number_modexp_u64(&ctx, &out, &base, 13, &mod); /* 4^13 mod 497 */
  limitless_number_to_str(&ctx, &out, buf, sizeof(buf), NULL); /* "445" */

  limitless_number_clear(&ctx, &base);
  limitless_number_clear(&ctx, &mod);
  limitless_number_clear(&ctx, &out);
  return 0;
}

C++: parse, operators, comparisons

#define LIMITLESS_IMPLEMENTATION
#include "limitless.hpp"

int main() {
  limitless::number a = limitless::number::parse("7/3");
  limitless::number b = 2;
  limitless::number c = (10 + a) * b;
  bool larger = c > a;
  return larger && c.str() == "74/3" ? 0 : 1;
}

Package consumption

CMake

project side:

find_package(Limitless CONFIG REQUIRED)
add_executable(app main.c)
target_link_libraries(app PRIVATE limitless::limitless)

build example:

cmake -S . -B build -DCMAKE_PREFIX_PATH=/path/to/limitless/install
cmake --build build

pkg-config

cc main.c $(pkg-config --cflags --libs limitless) -o app

Conan 2

conan profile detect --force
conan create . --version "$(cat LIMITLESS_VERSION.txt)"

consumer conanfile.txt example:

[requires]
limitless/0.1.0

[generators]
CMakeDeps
CMakeToolchain

vcpkg overlay port

$VCPKG_ROOT/vcpkg install limitless --overlay-ports=$PWD/packaging/vcpkg/ports

Local build and test

quick local matrix on unix-like hosts:

CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh default
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh limb64
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh noexceptions
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh m32
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh asan-ubsan
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh lsan
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh tsan
CC_BIN=cc CXX_BIN=c++ bash tests/ci/run_unix_matrix.sh extended-stress

coverage run (local):

python3 -m pip install gcovr
CC_BIN=gcc CXX_BIN=g++ LIMITLESS_DIFF_ITERS=800 bash tests/ci/run_coverage.sh

coverage report scope is the core C header implementation (limitless.h).

additional quality checks:

bash tests/ci/run_negative_compile.sh
bash tests/ci/run_clang_analyze.sh
bash tests/ci/run_clang_tidy.sh
bash tests/ci/run_cppcheck.sh
bash tests/ci/run_repo_lint.sh
bash tests/ci/run_fuzz_smoke.sh
bash tests/ci/run_bench_regression.sh

packaging smoke checks:

python3 -m pip install conan
bash tests/ci/packaging_smoke.sh

regenerate committed vectors:

python3 tests/gen_vectors.py

run standalone differential checks:

cc -std=c99 -Wall -Wextra -Werror -pedantic tests/ci/limitless_cli.c -o build/limitless_cli
bash tests/ci/run_differential.sh build/limitless_cli 5000

Release model

  • tags drive releases: vX.Y.Z (stable) or vX.Y.Z-rc... / vX.Y.Z-beta... (pre-release)
  • release workflow validates tag/version consistency first
  • release assets include:
    • source tar/zip
    • install-layout archive
    • SHA256SUMS
    • SPDX SBOM
    • GitHub provenance attestation

License

GPL-3.0-only. see LICENSE.

About

Limitless numbers in C and C++

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors