Loading repository data…
Loading repository data…
ckormanyos / repository
Wide-Integer implements a generic C++ template for uint128_t, uint256_t, uint512_t, uint1024_t, etc.
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
wide-integer implements a generic C++ template for extended width unsigned and signed integral types.
This C++ template header-only library implements drop-in big integer types
such as uint128_t, uint256_t, uint384_t, uint512_t, uint1024_t, uint1536_t, etc.
These can be used essentially like regular built-in integers.
Corresponding signed integer types such as int128_t, int256_t, and the like
can also be used.
The big integer class is called math::wide_integer::uintwide_t
(i.e., uintwide_t residing in the namespace math::wide_integer),
as shown in greater detail below.
wide-integer supports both unsigned as well as
signed integral types having width of
$1 {\ldots} 63 {\times} 2^N$
while being $16$, $24$, $32$ or larger.
In addition, small integer types such as software-synthesized versions of
uint24_t, uint48_t, uint64_t, uint96_t, uint128_t, etc.
(or signed counterparts of these) can also be created with wide-integer.
We also emphasize here that less-common types (i.e., those less common than, say,
uint128_t, uint256_t, uint512_t, etc.) can also be synthesized.
Types such as uint80_t made from five 16-bit limbs,
or uint96_t composed of three 32-bit limbs, or
other similar types can be readily synthesized with wide-integer.
wide-integer also features basic realizations of several
elementary and number theoretical functions such as root finding,
random distribution, Miller-Rabin primality testing,
greatest common denominator (GCD), least common multiplier (LCM),
integer division (i.e., divmod()) and more.
Inclusion of a single C++14 header file is all that is needed for using wide-integer, as shown in the examples.
uintwide_t should behave as closely as possible to the behaviors of signed and unsigned versions of built-in int.constexpr-ness.When working in your own project with wide-integer,
using the uintwide_t.h header
is straightforward. Identify the header within
its directory. Include this header path to the compiler's set
of include paths or in your project.
Then simply #include <uintwide_t.h> in the normal C++ way.
Easy application follows via traditional C-style typedef or alias
such as uint512_t. An instance of the defined type can be used very much
like a built-in integral type.
In the following code, for example,
the static uint512_t variable x is initialized with unsigned, integral value 3U.
The main subroutine subsequently computes $3^{301}$ with the specialized
wide-integer, namespace-specific function pow, which is found via ADL.
The approximate result is
$$3^{301}~{\approx}~4.10674{\times}~10^{143}\text{.}$$
See also the following informative links to Wolfram Alpha(R).
This example, compiled with successful output result, is shown in its entirety in the following short link to godbolt.
In particular,
#include <math/wide_integer/uintwide_t.h>
#include <iostream>
auto main() -> int
{
using uint512_t = ::math::wide_integer::uintwide_t<512U, std::uint32_t>;
const uint512_t x { 3U };
const auto p3 = pow(x, 301);
// 410674437175765127973978082146264947899391086876012309414440570235106991532497229781400618467066824164751453321793982128440538198297087323698003
std::cout << "p3: " << p3 << std::endl;
std::cout << "Cast p3 to double: " << double { p3 } << std::endl;
}
The code sequence above defines the local data type uint512_t with
an alias. The first template parameter 512U sets the binary width
(or bit count) while the second optional template parameter std::uint32_t
sets the internal limb type. The limb type must be unsigned and one of
std::uint8_t, std::uint16_t, std::uint32_t or on some systems
std::uint64_t. If the second template parameter LimbType is left blank,
the default limb type (i.e., uint_defaultlimb_t) is either
std::uint32_t or std::uint64_t, with $64$-bit limbs if
WIDE_INTEGER_HAS_LIMB_TYPE_UINT64 is defined (see also the relevant docs below).
The complete template signature of the uintwide_t class is shown below.
namespace math::wide_integer {
namespace detail { using size_t = std::uint32_t; }
using detail::size_t;
// Forward declaration of the uintwide_t template class.
template<const size_t Width2,
typename LimbType = uint_defaultlimb_t,
typename AllocatorType = void,
const bool IsSigned = false>
class uintwide_t;
// Here, uint_defaultlimb_t is either std::uint32_t or std::uint64_t
// (if WIDE_INTEGER_HAS_LIMB_TYPE_UINT64, see below) is defined.
} // namespace math::wide_integer
uintwide_t also has a third optional template parameter that
is used to set the allocator type employed for internal storage of the
big integer's data. The default allocator type is void
and uintwide_t uses stack allocation with an std::array-like internal representation.
Setting the allocator type to an actual allocator such as,
for instance, std::allocator<limb_type> activates allocator-based
internal storage for uintwide_t.
Using allocator-based storage reduces stack consumption and
can be especially beneficial for higher digit counts.
For low digit counts, the allocator type can
simply be left blank (thus defaulting to void)
or explicitly be set to void and stack allocation
will be used in either case.
If an allocator is supplied with any granularity other than limb_type
(in other words LimbType) such as std::allocator<void>, custom_allocator_type<char>, etc.,
then the uintwide_t class will internally rebind the allocator
to the granularity and unsigned-ness of limb_type using rebind_alloc
from std::allocator_traits.
The fourth template parameter IsSigned can be set to true
to activate a signed integer type. If left blank,
the default value of IsSigned is false
and the integer type will be unsigned.
Various interesting and algorithmically challenging examples have been implemented. It is hoped that the examples provide inspiration and guidance on how to use wide-integer.
std::numeric_limits for (unsigned) uint256_tand (signed) int256_t.uintwide_t.powm.gcd function.uintwide_t-based types.uintwide_t-based types.