Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/jibsen/wideint
C++ implementation of wide exact-width integer types
https://github.com/jibsen/wideint
cpp uint128 uint256
Last synced: 11 days ago
JSON representation
C++ implementation of wide exact-width integer types
- Host: GitHub
- URL: https://github.com/jibsen/wideint
- Owner: jibsen
- License: apache-2.0
- Created: 2022-01-24T21:08:19.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2024-03-17T11:11:35.000Z (8 months ago)
- Last Synced: 2024-03-18T11:47:54.664Z (8 months ago)
- Topics: cpp, uint128, uint256
- Language: C++
- Homepage:
- Size: 343 KB
- Stars: 4
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
wideint - wide exact-width integer types
========================================Copyright (c) 2022 Joergen Ibsen
[![wideint CI](https://github.com/jibsen/wideint/actions/workflows/wideint-ci-workflow.yaml/badge.svg)](https://github.com/jibsen/wideint/actions)
About
-----wideint is a C++ implementation of wide *exact-width* integer types.
~~~.cpp
#include
#include "wideint.hpp"int main()
{
// Type alias for convenience
using uint128 = wideint::wuint<4>;constexpr auto p = uint128("9223372036854775337");
constexpr auto q = uint128("4611686018427387847");// Print product (42535295865117305235085505148949129439)
std::cout << p * q << '\n';
}
~~~While doing [Advent of Code](https://adventofcode.com/) to pick up some
C++20, I came across a problem where I wanted to do a computation on values
larger than what fits in an `unsigned long long`. The C++ standard library
does not include a big integer type yet, so I would either have to use one
of the stable, well-tested, highly efficient libraries available, or write
my own ad hoc solution, and hopefully learn a few things along the way.Caveat
------wideint has not been thoroughly tested, and some of the algorithms used may
be slow compared to what you would get with one of the established big number
libraries. Also, being exact-width and stack-allocated means it is suitable
for bounded computations on relatively small values.Requirements
------------wideint requires `std::uint32_t` and `std::uint64_t` to be available. It
uses some C++20 features which may not be available in all compilers.Details
-------A wideint stores its value in a `std::array` of `std::uint32_t`. It takes
the size of this array as a template argument. So a `wuint<3>`, for example,
stores a 96-bit value, while a `wuint<4>` stores a 128-bit value.While it is possible to create a wideint with 32- or 64 bits, use the
built-in types `std::uint32_t` and `std::uint64_t` instead.There is no implicit conversion from `std::uint32_t` or `std::string_view`
to wideint. If you want to initialize a wideint with either, you will have
to do so explicitly:~~~.cpp
// This does not compile, there is no implicit conversion
// uint128 a = 5;// Use either of these instead
uint128 b(5);
uint128 c = uint128(5);
auto d = uint128(5);
~~~As special cases, modulus (`wuint % uint32_t`) and bitwise AND
(`wuint & uint32_t`) with a `std::uint32_t` on the right return a
`std::uint32_t` instead of a `wuint`.Most operations are `constexpr`.
Functionality
-------------Besides the usual arithmetic and comparison operators, the following is
available.For both signed and unsigned wideints:
- `is_zero` and `is_negative` member functions
- `getbit` and `setbit` member functions
- `abs`
- `to_string`
- `from_chars` and `to_chars`
- specialization of `std::hash`For unsigned wideints:
- `gcd`, `lcm`, and `sqrt`
- `has_single_bit`, `bit_ceil`, `bit_floor` `bit_width`, `countl_zero`,
`countl_one`, `countr_zero`, and `countr_one` analogous to the ``
headerSigned values
-------------There is a signed wideint type, `wideint::wint`, which interprets the value
it stores as a two's complement representation.~~~.cpp
#include
#include
#include "wideint.hpp"template
constexpr T gcd_euclid(const T &x, const T &y)
{
auto a = x;
auto b = y;while (b != 0) {
a = std::exchange(b, a % b);
}return abs(a);
}int main()
{
// Type alias for convenience
using int128 = wideint::wint<4>;// Three large primes
constexpr auto p = int128("9223372036854775337");
constexpr auto q = int128("4611686018427387847");
constexpr auto r = int128("2305843009213693907");// Print GCD of p * r and -q * r (2305843009213693907)
std::cout << gcd_euclid(p * r, -q * r) << '\n';
}
~~~Output
------There is a `to_string()` function that converts a wideint to a `std::string`.
There are operator overloads for stream input and output. You can disable
these by defining `WIDEINT_NO_IOSTREAMS`.Alternatives
------------- [Abseil Numerics](https://abseil.io/docs/cpp/guides/numeric)
- [Boost.Multiprecision](https://www.boost.org/doc/libs/release/libs/multiprecision/)
- [GMP](https://gmplib.org/)
- [InfInt](https://github.com/sercantutar/infint)
- [mp++](https://github.com/bluescarni/mppp)
- [MPIR](https://github.com/wbhart/mpir)
- [wide-integer](https://github.com/ckormanyos/wide-integer)