Simple Long Integer Math for C++
SLIMCPP is a C++ header-only library that implements long integers that exceed maximum size of native type supported by a specific compiler by 2-4 times. All classes, methods and functions were not created or designed to work with huge numbers, for which there are specialized big integer mathematical libraries. In some cases, it is necessary to temporarily perform calculations with precision exceeding the maximum supported size of integers, and then return the result to its native size again. The conditions are ideal for SLIMCPP. The main features:
The library implements two main classes:
namespace slim
{
template<typename native_t = uintmax_t, uint_t size = 2>
class long_uint_t; // unsigned integer
template<typename native_t = uintmax_t, uint_t size = 2>
class long_int_t; // signed integer
} // namespace slim
where native_t may be one of base unsigned type and size must by power of two.
The library implements four predefined types: uint128_t, uint256_t, int128_t, int256_t. You can use them in your project by include code below:
#include <slimcpplib/long_int.h> // Include all integers support
// or
#include <slimcpplib/long_uint.h> // Include only unsigned integers support
namespace your_namespace
{
using uint128_t = slim::uint128_t;
using uint256_t = slim::uint256_t;
using int128_t = slim::int128_t;
using int256_t = slim::int256_t;
using namespace slim::literals;
} // namespace your_namespace
constexpr auto uo = 03766713523035452062041773345651416625031020_ui128; // octal unsigned integer
constexpr auto ud = 338770000845734292534325025077361652240_ui128; // decimal unsigned integer
constexpr auto uh = 0xfedcba9876543210fedcba9876543210_ui128; // hexadecimal unsigned integer
constexpr auto io = -03766713523035452062041773345651416625031020_si128; // octal signed integer
constexpr auto id = -338770000845734292534325025077361652240_si128; // decimal signed integer
constexpr auto ih = -0xfedcba9876543210fedcba9876543210_si128; // hexadecimal signed integer
also supported (') separator for integer literals:
constexpr auto u = 0xfedcba98'76543210'fedcba98'76543210_ui128; // hexadecimal unsigned integer
const uint128_t u; // construct uninitialized unsigned integer
const uint128_t u = 1U; // construction from unsigned integer
const int128_t s = -1; // construction from signed integer
const uint128_t u = 10000_ui128; // construction from long unsigned integer
const int128_t u = -10000_si128; // construction from long signed integer
const uint128_t u = true; // construction from boolean value
long_uint_t type supports following operators:
==, !=, <, <=, >, >=, <<=, <<, >>=, >>, +=, +, ++, -=, -, --, *=, *, /=, /, %=, %, ~, &=, &, |=, |, ^=, ^
long_int_t type supports following operators:
==, !=, <, <=, >, >=, +=, +, ++, -=, -, --, *=, *, /=, /, %=, %
The library implements the muldiv method for faster calculation of the following expressions: (a * b / c). It can be used with signed and unsigned integers.
template<typename type_t>
constexpr type_t muldiv(const type_t& value, const type_t& multiplier, const type_t& divider) noexcept;
std::cout << std::oct << 338770000845734292534325025077361652240_ui128 << "\n"; // octal
std::cout << std::dec << 03766713523035452062041773345651416625031020_ui128 << " \n"; // decimal
std::cout << std::hex << 0xfedcba9876543210fedcba9876543210_ui128 << "\n"; // hexadecimal
main.cpp - examples of using the main interface of the library with comments.
All measurements are not intended to be a strong performance tests and are provided simply for relative comparison of the operation costs. All measurements were taken on Intel (R) Core (TM) i5-9400F CPU @ 2.90GHz in a 64-bit configuration with 128-bit integers.
Operation | Average time (in ns.) |
---|---|
Unsigned addition | 0.25 |
Signed addition | 0.25 |
Unsigned subtraction | 0.25 |
Signed subtraction | 0.25 |
Unsigned multiplication | 7.00 |
Signed multiplication | 7.00 |
Unsigned division | 15.00 |
Signed division | 20.00 |
Unsigned muldiv() | 20.00 |
Signed muldiv() | 25.00 |