PackageTrack
Sign in Get early access

bnum

Fixed-size integer types with generic signedness, bit width and overflow behaviour.

0.14.4 14M downloads/mo #2635 most downloaded on crates.io isaacholt100/bnum

What this package is like to depend on

Last release 5 months ago

24 Mar 2026

Release timing varies

gaps range from 8 days to 12 months

Some releases are documented

notes for 10 of 21 stable releases

Nothing withdrawn

no release was ever pulled

4 years old

21 releases · first in 2022

5 releases in the last 12 months

see the full history below

Release timeline

21 releases · Jul 2022 to Mar 2026
2023 2024 2025 2026
Release Pre-release

Releases

latest 21
  1. 0.14.4 24 Mar 2026
    Release notes

    Fixes #72, also fixes a bug in the quickcheck::Arbitrary and rand::Distribution and rand::Fill traits where the padding bits of integers with non-multiple-of-8 bit widths were not set properly.

    Open source →
  2. 0.14.3 19 Mar 2026
    Release notes

    Patch release: update the Cargo.toml description and fix display of code examples in the README.

    Open source →
  3. 0.14.2 18 Mar 2026
    Release notes

    This implements the fix #68 which caused the crate tests to not compile when the "alloc" feature was disabled.

    Open source →
  4. 0.14.1 17 Mar 2026
    Release notes

    This version fixes #65.

    Auto-generated release notes:

    What's Changed

    New Contributors

    Full Changelog: v0.14.0...v0.14.1

    Open source →
  5. 0.14.0 16 Mar 2026
    Release notes

    This release is by far the most significant upgrade of the crate so far, with a greatly simplified API, performance improvements, increased customisability, and new functionality.

    Significant changes

    From 8 integer types to a single unified integer type

    The biggest change is that instead of there being 4 unsigned integer types (BUint, BUintD32, BUintD16, BUintD8) and 4 signed integer types ( BInt, BIntD32, BIntD16, BIntD8), there is now a single type Integer, which has a const-generic parameter S of type bool, which controls whether the type behaves as an unsigned or signed integer.

    In previous versions of the crate, there was a separate integer type for each of the 4 allowed underlying digit types: u8, u16, u32, and u64. The reason for this was that narrower digit types allowed for more fine-grained bit widths, while wider digit types meant faster performance. Thus, there was a trade-off between bit width customisability, and speed.

    Integer avoids this trade-off entirely by being stored as an array of u8 digits, but iterating over wider digits (by "chunking" together u8 digits) during computations. The performance of a given method on Integer has been benchmarked with each possible choice of chunked digit (u8, u16, u32, u64, u128), and the digit giving the fastest implementation was chosen.

    The types Uint and Int are aliases Integer, with the const-generic parameter S specified to be false and true respectively.

    Arbitrary bit widths

    Integer has another const-generic parameter B of type usize to specify the bit width of the integer as any integer between 2 and 2^32 - 1; in previous versions, the bit width of the integer was inferred from the byte width, so had to be a multiple of 8.

    const-generic overflow behaviour

    The final const-generic parameter Integer controls its behaviour when arithmetic overflow occurs. There are 3 possible behaviours: wrap around, panic, or saturate. By default, the behaviour is wrapping if the overflow-checks flag is disabled, and is panicking if overflow-checks is enabled.

    The full set of generic parameters of Integer<S, N, B, OM> are the signedness S, the byte width N, the bit width B, and the overflow mode OM. For example:

    type A = Integer<true, 3, 23, 0>; // signed 23-bit integer with wrapping overflow behaviour
    type B = Integer<false, 20, 155, 2>; // unsigned 155-bit integer with saturating overflow behaviour

    Easy construction of integer types and values

    In previous versions, in order to construct integers from a specified list of digits, the from_str_radix had to be used, e.g.

    let a = U256::from_str_radix("abcdef", 16).unwrap()

    There was no way of constructing integers from Rust integer literals at compile time. In this release, the n! macro is introduced, which takes an integer literal, and returns an integer whose value corresponds to the literal, e.g.

    let a = n!(0xabcdef_U256);

    Similarly to how integer literals are handled for the primitive integer types, if literal is specified without a suffix, then type inference is performed, e.g.

    let b: I512 = n!(1234);

    is valid. As in the case of primitive integers, if an invalid literal is encountered, then a compile error is triggered, e.g.

    let a = n!(1a23_U24)

    would cause a compile error. The one difference is that let c = 0 assigns a type of i32 to c by default, whereas let c = n!(0) would result in a compile error (unless c was subsequently used in a way that type inference for c could be performed by the compiler).

    bnum now also supports construction of specific integer types via the t! macro. The t! macro takes a "type descriptor" which is an identifier encoding the specific values of the const-generic parameters of Integer. For example, if you wanted a 155-bit signed integer which has wrapping behaviour on overflow, you would write t!(I155w), which outputs Integer<true, 20, 155, 0>.

    let a: t!(I155w) = n!(1234);
    
    fn add_one(int: t!(I155w)) -> t!(I155w) {
        int + n!(1)
    }
    let b = add_one(a);

    The n! and t! macros are both declarative, not procedural, so add minimal compile-time overhead and do not introduce any dependencies to bnum (which is still zero-dependency by default).

    All other changes

    Major changes

    • Remove the Add<Digit>, Div<Digit> and Rem<Digit> impls for unsigned integers (use the Add<Self>, Div<Self> and Rem<Self> impls instead).
    • Remove the parse_str_radix method (use from_str_radix(...).unwrap(), or the n! macro if appropriate).
    • The optional rand dependency is now version 0.10 of that crate.
    • Remove the Slice struct and try_fill_slice function from the crate's random module (these are superseded by the implementation of the Fill trait from rand 0.10).
    • Remove the parse_bytes method (use from_ascii_radix instead).
    • Remove as_bits, as_bits_mut from signed integers (either use as_bytes or as_bytes_mut instead, methods like set_bit are now defined for signed integers as well as unsigned).
    • Remove numeric associated constants (e.g. ZERO, TWO, NEG_ONE) from integers, as these values can now be easily constructed with the n! macro.
    • Remove {to,from}_{be,le} methods from integers, as not portable (and it didn't make sense to have them anyway as bnum integers are always stored in little-endian byte order).
    • Remove from_digit method from unsigned integers (use the As trait instead).
    • Remove {from,to}_radix_{be,le} from signed integers (only makes sense to have this for unsigned integers).
    • Remove the CastFrom trait from the prelude.
    • Remove the bits method from signed integers and rename the bits method on unsigned integers to bit_width, which now takes self instead of &self.
    • Remove BTryFrom trait (use the TryFrom<&Integer> for Integer, TryFrom<Int> for Uint or TryFrom<Uint> for Int impls instead).
    • Change From<primitive_int> impls to TryFrom<primitive_int> (use the As trait instead for infallible conversions).
    • Remove From conversions between Uint and [u8; N].

    Minor changes

    • Add implementations of the FromBytes, ToBytes, ConstZero, ConstOne and OverflowingMul traits from the num_traits crate.
    • The unchecked_... methods are now const.
    • Put features requiring the alloc crate behind an alloc feature, which allows for usage in no-alloc environments.
    • The crate now uses the 2024 edition of Rust.
    • The minimum supported Rust version (MSRV) is now 1.87.0.
    • Add from_ascii and from_ascii_radix methods.
    • Add unchecked_neg method to signed integers.
    • Add checked_signed_diff, overflowing_sub_signed, wrapping_sub_signed, checked_sub_signed, saturating_sub_signed methods to unsigned integers.
    • Add a Debug impl for integers when the alloc feature is disabled, which formats the integer as a padded hex string.
    • Add compile-time assertions to validate the bit width of integers (must be in the range [2, 2^32).
    • Add TryFrom<&Integer> for Integer, TryFrom<Int> for Uint or TryFrom<Uint> for Int impls.
    • Implement the core::error::Error trait for TryFromIntError, TryFromCharError, and ParseIntError.

    Patches

    • Fix behaviour of the is_multiple_of method (previously, it incorrectly panicked if rhs was zero).
    • Fix behaviour of mod_floor and div_floor methods of the num_integer::Integer impl for signed integers.
    • Fix behaviour of the wrapping_sh{l, r} and overflowing_sh{l,r} methods when shift exceeds the bit width of the integer.
    Open source →
  6. 0.13.0 08 Mar 2025
    Release notes

    This release adds support for some more traits from the num_traits crate, implements a few new methods, fixes three methods which were incorrectly did not panic, and allows testing on stable.

    Minor changes

    • It is now possible to run bnum's unit tests on stable Rust. This was not possible before since the tests included those for methods whose counterparts on Rust's primitives are only available on nightly. The tests for such methods are now gated behind the nightly crate feature (and nightly Rust is still required to test these specific methods).
    • Added implementation of the OverflowingAdd and OverflowingSub traits from the num_traits crate.
    • Added unbounded_shl and unbounded_shr methods to signed and unsigned integers.
    • Added as_bits and as_bits_mut to signed integers.

    Patches

    • In previous versions of bnum, the documentation for to_str_radix, to_radix_be and to_radix_le stated that these methods panicked on invalid radices, where in fact this was not the case. As of this version, they now panic correctly on invalid radices (as per the documentation).
    • The set_bit method on unsigned ints is now branchless.

    Auto-generated release notes:

    What's Changed

    New Contributors

    Full Changelog: v0.12.1...v0.13.0

    Open source →
  7. 0.12.1 01 Jan 2025
    Release notes

    This release fixes a few incorrect implementations of some methods.

    Patches

    • Fixed #47, by making midpoint round to zero for signed integers.
    • Changed the Debug implementation of ParseIntError to match that of core::num::ParseIntError.
    • Fixed the lcm method on num-integer::Integer for signed integers (now always returns non-negative values)
    • Corrected more cases where a PosOverflow error is returned instead of an InvalidDigit error when parsing integers (however there some edge cases where PosOverflow should be returned and now isn't, this will be fixed at some point).

    Auto-generated release notes:

    What's Changed

    Full Changelog: v0.12.0...v0.12.1

    Open source →
  8. 0.12.0 20 Sep 2024
    Release notes

    This release introduces a number of new methods, as well as support for the borsh crate.

    Major Changes

    • The latest nightly compiler (1.83.0) does not support user-defined const traits, and so the nightly crate feature no longer makes the CastFrom and As traits const. This means the implementations of these traits on bnum integers are no longer const either.

    Minor Changes

    • Added (optional) support for the borsh crate (this enables serialisation and deserialisation using this crate).
    • Added digits_mut and set_bit methods to unsigned integers, allowing for manipulation without copying the value.
    • Added cast_signed method for unsigned integers and cast_unsigned method for signed integers.
    • Added midpoint method for all integers.
    • Added carrying_add and borrowing_sub methods for signed integers.
    • Added strict_... arithmetic methods for all integers.

    Patches

    • Added (bnum) prefix to panic messages that mistakenly did not include it.

    Auto-generated release notes:

    What's Changed

    New Contributors

    Full Changelog: v0.11.0...v0.12.0

    Open source →
  9. 0.11.0 06 Mar 2024
    Release notes

    This release fixes #39, and makes all ilog* methods panic with the same message as Rust's primitive integers (with the (bnum) prefix, as for other bnum panic messages).

    Major Changes

    • ilog* methods now panic for invalid inputs in release mode as well as debug mode.

    Patches

    • ilog* panic messages now match that of Rust's primitives.

    What's Changed

    Full Changelog: v0.10.0...v0.11.0

    Open source →
  10. 0.10.0 23 Nov 2023

    Nothing published for this version

  11. 0.9.1 25 Oct 2023

    Nothing published for this version

  12. 0.9.0 28 Sep 2023

    Nothing published for this version

  13. 0.8.1 24 Nov 2023
    Release notes

    This release fixes #36. For more info, see the release notes for v0.10.0.

    Open source →
  14. 0.8.0 23 Jul 2023

    Nothing published for this version

  15. 0.7.0 28 May 2023

    Nothing published for this version

  16. 0.6.0 07 Mar 2023

    Nothing published for this version

  17. 0.5.0 02 Jan 2023

    Nothing published for this version

  18. 0.4.0 24 Dec 2022

    Nothing published for this version

  19. 0.3.0 11 Sep 2022

    Nothing published for this version

  20. 0.2.0 09 Aug 2022

    Nothing published for this version

  21. 0.1.0 10 Jul 2022

    Nothing published for this version

Every package, every release, already written down.

The archive is open and free. Watching your own project is what we are building next.

Browse the archive