### 8 breaking releases

new 0.9.0 | Sep 28, 2023 |
---|---|

0.8.0 | Jul 23, 2023 |

0.7.0 | May 28, 2023 |

0.6.0 | Mar 7, 2023 |

0.1.0 | Jul 10, 2022 |

#**77** in Cryptography

**43,323** downloads per month

Used in **438** crates
(2 directly)

**MIT/Apache**

440KB

10K
SLoC

# bnum

Arbitrary precision, fixed-size signed and unsigned integer types for Rust.

## Overview

The aim of this crate is to provide integer types of arbitrary fixed size which behave exactly like Rust's primitive integer types:

, `u8`

, `i8`

, `u16`

, etc. Nearly all methods defined on Rust's signed and unsigned primitive integers are defined `i16`

's signed and unsigned integers. Additionally, some other useful methods are provided, mostly inspired by the `bnum`

and `BigInt`

types from the `BigUint`

crate.`num_bigint`

This crate uses Rust's const generics to allow creation of integers of arbitrary size that can be determined at compile time. Unsigned integers are stored as an array of digits (primitive unsigned integers) of length

. This means all `N`

integers can be stored on the stack, as they are fixed size. Signed integers are simply stored as an unsigned integer in two's complement.`bnum`

defines 4 unsigned integer types: each uses a different primitive integer as its digit type. `bnum`

uses `BUint`

as its digit, `u64`

uses `BUintD32`

, `u32`

uses `BUintD16`

and `u16`

uses `BUintD8`

. The signed integer types, `u8`

, `BInt`

, `BIntD32`

and `BIntD16`

are represented by these unsigned integers respectively.`BIntD8`

and `BUint`

are the fastest as they store (and so operate on) the least number of digits for a given bit size. However, the drawback is that the bit size must be a multiple of `BInt`

(`64`

). This is why other integer types are provided as well, as they allow the bit size to be a multiple of `bitsize = N * 64`

`32`

, `16`

, or `8`

instead. When choosing which of these types to use, determine which of `64``,` `32``,` `16``,` `8`

is the largest multiple of the desired bit size, and use the corresponding type. For example, if you wanted a 96-bit unsigned integer, 32 is the largest multiple of 96 out of these, so use `BUintD32``<`3`>`

. A 40-bit signed integer would be `BIntD8``<`5`>`

.## Why bnum?

**Zero dependencies by default**:

does not depend on any other crates by default. Support for crates such as`bnum`

and`rand`

can be enabled with crate features.`serde`:

compatible`no-std`

can be used in`bnum`

environments, provided that the`no_std`

and`arbitrary`

features are not enabled.`quickcheck`**Compile-time integer parsing**: the

and`from_str_radix`

methods on`parse_str_radix`

integers are`bnum`

, which allows parsing of integers from string slices at compile time. Note that this is more powerful than compile-time parsing of integer literals. This is because it allows parsing of strings in all radices from`const`

to`2`

inclusive instead of just`36`

,`2`

,`8`

and`10`

. Additionally, the string to be parsed does not have to be a literal: it could, for example, be obtained via`16`

, or`include_str!``(``"`...`"``)`

.`env!``(``"`...`"``)`: nearly all methods defined on

evaluation`const`

integers are`bnum`

, which allows complex compile-time calculations.`const`

## Installation

To install and use

, simply add the following line to your `bnum`

file in the `Cargo .toml`

`[``dependencies``]`

section:`bnum = "0.9.0"
`

Or, to enable various

features as well, add for example this line instead:`bnum`

`bnum = { version = "0.9.0", features = ["rand"] } ``# enables the "rand" feature`

## Example Usage

**NB: the examples in the documentation use specific type aliases (e.g. **

`,`

`U256`

`, or`

`U512`

`,`

`I256`

`) to give examples of correct usage for most methods. There is nothing special about these types in particular: all methods that are shown with these are implemented for all unsigned/signed`

`I512`

`bnum`integers for any value of

`N`.

`//` As of version 0.6.0, you can parse integers from string slices at compile time with the const methods `from_str_radix` or `parse_str_radix`:
`use` `bnum``::``types``::``{``U256``,` `I256``}``;`
`use` `bnum``::``errors``::`ParseIntError`;`
`//` `parse_str_radix` returns an integer, and panics if the string fails to parse
`const` `UINT_FROM_DECIMAL_STR``:` `U256` `=` `U256``::`parse_str_radix`(``"`12345678901234567890`"``,` `10``)``;`
`//` If you are not sure that the string will successfully parse, you can use `from_str_radix` which returns a `Result`
`const` `RESULT_INT_FROM_HEXA_STR``:` `Result``<`I256, ParseIntError`>` `=` `I256``::`from_str_radix`(``"`-1234567890abcdef`"``,` `16``)``;`
`assert_eq!``(``format!``(``"``{}``"``,` `UINT_FROM_DECIMAL_STR``)``,` `"`12345678901234567890`"``)``;`
`assert_eq!``(``format!``(``"``{:x}``"``,` `RESULT_INT_FROM_HEXA_STR``.``unwrap``(``)``.``abs``(``)``)``,` `"`1234567890abcdef`"``)``;`

`//` Calculate the `n`th Fibonacci number, using the type alias `U512`.
`use` `bnum``::``types``::``U512``;` `//` `U512` is a type alias for a `BUint` which contains 8 `u64` digits
`//` Calculate the nth Fibonacci number
`fn` `fibonacci``(``n``:` `usize``)`` ``->` U512 `{`
`let` `mut` f_n`:` `U512` `=` `U512``::``ZERO``;` `//` or `U512::from(0u8)`
`let` `mut` f_n_next`:` `U512` `=` `U512``::``ONE``;` `//` or `U512::from(1u8)`
`for` `_` `in` `0``..`n `{`
`let` temp `=` f_n_next`;`
f_n_next `+=` f_n`;`
f_n `=` temp`;`
`}`
f_n
`}`
`let` n `=` `100``;`
`let` f_n `=` `fibonacci``(`n`)``;`
`println!``(``"`The `{}`th Fibonacci number is `{}``"``,` n`,` f_n`)``;`
`//` Prints "The 100th Fibonacci number is 354224848179261915075"
`assert_eq!``(`f_n`,` `U512``::`from_str_radix`(``"`354224848179261915075`"``,` `10``)``.``unwrap``(``)``)``;`

`//` Construct an 80-bit signed integer
`//` Out of [64, 32, 16, 8], 16 is the largest multiple of 80, so use `BIntD16`
`use` `bnum``::`BIntD16`;`
`type` `I80` `=` `BIntD16``<`5`>``;` `//` 80 / 16 = 5
`let` neg_one `=` `I80``::``NEG_ONE``;`
`assert_eq!``(`neg_one`.``count_ones``(``)``,` `80``)``;` `//` signed integers are stored in two's complement so `-1` is represented as `111111...`

## Features

### Fuzzing

The

feature derives the `arbitrary`

trait from the `Arbitrary`

crate. `arbitrary`**Note: currently, this feature cannot be used with **

`no_std`(see https://github.com/rust-fuzz/arbitrary/issues/38).

### Random Number Generation

The

feature allows creation of random `rand`

integers via the `bnum`

crate.`rand`

### Serialization and Deserialization

The

feature enables serialization and deserialization of `serde`

integers via the `bnum`

and `serde`

crates.`serde_big_array`

`num_traits`

and `num_integer`

trait implementations

`num_traits`

`num_integer`

The

feature includes implementations of traits from the `numtraits`

and `num_traits`

crates, e.g. `num_integer`

, `AsPrimitive`

, `Signed`

and `Integer`

.`Roots`

### Quickcheck

The

feature enables the `quickcheck`

trait from the `Arbitrary`

crate. `quickcheck`**Note: currently, this feature cannot be used with **

`no_std`(see https://github.com/rust-fuzz/arbitrary/issues/38).

### Zeroize

The

feature enables the `zeroize`

trait from the `Zeroize`

crate.`zeroize`

### Valuable

The

feature enables the `valuable`

trait from the `Valuable`

crate.`valuable`

### Nightly features

Activating the

feature will enable the `nightly`

, `from_be_bytes`

, `from_le_bytes`

, `from_ne_bytes`

, `to_be_bytes`

and `to_le_bytes`

methods on `to_ne_bytes`

's unsigned and signed integers and will make the `bnum`

methods `unchecked_ ...`

`const`

. This comes at the cost of only being able to compile on nightly. The nightly features that this uses are `generic_const_exprs`

, `const_trait_impl`

and `const_option_ext`

.## Testing

This crate is tested with the

crate as well as with specific edge cases. The outputs of methods are compared to the outputs of the equivalent methods of primitive integers to ensure that the behaviour is identical.`quickcheck`

## Documentation

If a method is not documented explicitly, it will have a link to the equivalent method defined on primitive Rust integers (since the methods have the same functionality).

**NB: **

`bnum`is currently pre-

`. As per the Semantic Versioning guidelines, the public API may contain breaking changes while it is in this stage. However, as the API is designed to be as similar as possible to the API of Rust's primitive integers, it is unlikely that there will be a large number of breaking changes.`

`1.``0``.``0`## Known Issues

At the moment, the

trait is implemented for `From`

's integers, from all the Rust primitive integers. However, this behaviour is not quite correct. For example, if a 24-bit wide unsigned integer were created (`bnum`

), this should not implement `BUintD8 <3>`

`From``<``u32``>`

, etc. and should implement `TryFrom``<``u32``>`

instead. To ensure correct behaviour, the `FromPrimitive`

trait from the `num_traits`

crate can be used instead, as this will always return an `Option`

rather than the integer itself.The

trait is implemented for `num_traits ::`NumCast

`bnum`

's integers but will panic if its method `from`

is called, as it is not possible to guarantee a correct conversion, due to trait bounds enforced by `NumCast`

. This trait should therefore never be used on `bnum`

's integers. The implementation exists only to allow implementation of the `num_traits``::`PrimInt

trait for `bnum`

's integers.## Prior bugs

The short list of bugs in previous versions can be found at

.`changes /prior-bugs.md`

## Future Work

This library aims to provide arbitrary, fixed precision equivalents of Rust's 3 built-in number types: signed integers, unsigned integers and floats. Signed and unsigned integers have been implemented and fully tested, and will aim to keep up to date with Rust's integer interface. (e.g. when a new method is implemented on a Rust primitive integer, this library will attempt to keep in step to include that method as well. This includes nightly-only methods.)

Currently, arbitrary precision fixed size floats are being worked on but are incomplete. Most of the basic methods, such as arithmetic and classification, have been implemented, but at the moment there is no implementation of the transcendental floating point methods such as

, `sin`

, `exp`

, etc.`log`

Additionally, a proc macro for parsing numeric values will be developed at some point, which will allow easier creation of large constant values for

's numeric types.`bnum`

## Licensing

is licensed under either the MIT license or the Apache License 2.0.`bnum`

#### Dependencies

~0–485KB