smallnum

crates.io GitHub Actions

Compile-time size optimization for numeric primitives. Macros return smallest numeric type capable of fitting a static bounds. For unsigned integers, macro input is a maximum. For signed integers, macro input may be a maximum or a minimum.

Example: Collection Index

When the size of a collection is known at compile-time, the variable used to index it can be size-optimized.

```rust use smallnum::{smallunsigned, SmallUnsigned}; use core::mem::sizeof_val;

const MAXSIZE: usize = 500; let mut myarray: [u8; MAXSIZE] = [0x00; MAXSIZE];

let idx: usize = 5; let smallidx: smallunsigned!(MAX_SIZE) = 5;

// Equivalent values myarray[idx] = 0xff; asserteq!(myarray[idx], myarray[small_idx.usize()]);

// Memory savings (6 bytes on a 64-bit system)

[cfg(targetpointerwidth = "64")]

asserteq!(sizeofval(&idx) - sizeofval(&smallidx), 6); ```

Example: Tree Node Metadata

When the maximum capacity of a tree is known at compile time, metadata stored in every node can be size-optimized.

```rust use smallnum::smallunsigned; use core::mem::sizeof;

const MAXCAPACITY: usize = 50000;

// Regular node in a binary tree pub struct BinTree { value: T, leftchild: Option>>, rightchild: Option>>, subtree_size: usize, }

// Node with size-optimized metadata pub struct SmallBinTree { value: T, leftchild: Option>>, rightchild: Option>>, subtreesize: smallunsigned!(MAX_CAPACITY), }

// Per-node memory savings (8 bytes on a 64-bit system)

[cfg(targetpointerwidth = "64")]

asserteq!(sizeof::>() - size_of::>(), 8); ```

Example: Index-based Graphs

When implementing an {index,arena}-based graph whose maximum capacity is known at compile-time, indexes stored in every structure (edge or node) can be size-optimized.

```rust use smallnum::smallunsigned; use core::mem::sizeof;

const MAXCAPACITY: usize = 50000;

// Based on "Modeling graphs in Rust using vector indices" by Niko Matsakis (April 2015) // http://smallcultfollowing.com/babysteps/blog/2015/04/06/modeling-graphs-in-rust-using-vector-indices/

// Unoptimized indexes pub type NodeIdx = usize; pub type EdgeIdx = usize;

pub struct EdgeData { target: NodeIdx, nextoutgoingedge: Option }

// Optimized indexes pub type SmallNodeIdx = smallunsigned!(MAXCAPACITY); pub type SmallEdgeIdx = smallunsigned!(MAXCAPACITY);

pub struct SmallEdgeData { target: SmallNodeIdx, nextoutgoingedge: Option }

// Per-edge memory savings (18 bytes on a 64-bit system)

[cfg(targetpointerwidth = "64")]

asserteq!(sizeof::() - size_of::(), 18); ```

Macro <-> Type Selection Set