num-traits

Numeric traits for generic mathematics in Rust, from Zero and One to Float and PrimInt

Library
Cargo
v0.2.19
976 stars
Apache License 2.0

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
43 /100 Fair
Development Activity 12
Maintenance 0
Community 72
Maturity 60
Momentum 28

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
79 /100 Good
Architecture 85
Code Quality 82
Innovation 78
Learning Curve 70

num-traits defines a set of composable traits that let Rust code be generic over numeric types instead of hard-coding f32, f64, i32, or u64. It underpins the wider rust-num ecosystem (num, num-complex, num-bigint, num-rational) and is a dependency of thousands of crates that need to write one algorithm that works across integers, floats, and custom numeric types.

The crate is #![no_std] by default, so it works in embedded and kernel contexts, with an optional libm feature to bring floating-point operations (like sqrt or sin) to platforms without the standard library. Traits are split into small, focused pieces (Zero, One, Num, Float, PrimInt, Bounded, Signed) so generic code only needs to require the exact capabilities it uses.

What You Get

  • Identity and arithmetic traits: Zero, One, Num, NumOps, and their checked/saturating/wrapping variants
  • Float and FloatConst traits exposing transcendental operations (sqrt, sin, ln) generically, with libm support for no_std
  • PrimInt trait unifying integer-specific operations like bit rotation and leading/trailing zero counts
  • Bounded, Signed, and Unsigned traits for range and sign-aware generic code
  • AsPrimitive, FromPrimitive, ToPrimitive, and NumCast for ergonomic numeric conversions
  • Full no_std compatibility with an optional libm feature for float ops without the standard library

Common Use Cases

  • Writing a single generic function or struct that works over f32, f64, and every integer type without duplication
  • Building numeric libraries (linear algebra, statistics, physics simulation) that need to be generic over precision
  • Implementing custom numeric types (fixed-point, complex, big integers) that plug into the standard numeric trait ecosystem
  • Targeting embedded or no_std environments while still needing generic floating-point math via the libm feature

Under The Hood

Architecture num-traits organizes its API as a set of narrowly-scoped traits split across dedicated modules (bounds.rs, cast.rs, float.rs, identities.rs, int.rs, ops/, pow.rs, real.rs, sign.rs), each re-exported from lib.rs so consumers can use num_traits::{Zero, One, Float} directly; the crate itself contains no concrete numeric types, only trait definitions and blanket implementations for Rust’s built-in primitives, keeping it a pure abstraction layer that other rust-num crates (num-complex, num-bigint, num-rational) and downstream numeric libraries build concrete types against.

Tech Stack The crate is written in pure, dependency-light Rust (edition 2021, MSRV 1.60), with a single optional runtime dependency on libm for software floating-point implementations when std is disabled, and autocfg as a build-time dependency for detecting compiler capabilities; it is #![no_std] by default and gates std-only functionality (like native float transcendental functions) behind Cargo features, making it viable in embedded, WASM, and kernel-level contexts.

Code Quality The tests/ directory contains dedicated integration test files per concern area (e.g. cast.rs), and the crate additionally embeds extensive doctested examples directly in trait documentation, which double as both documentation and correctness checks under cargo test --doc; the code favors small, single-purpose traits with blanket impls over primitives, and CI (visible via the ci/ directory and GitHub Actions badge) exercises multiple feature combinations and MSRV compatibility.

API Design The API is deliberately minimal and composable — traits like Zero, One, and Num are small enough to be understood at a glance, and free functions (zero(), one(), pow(), cast()) offer ergonomic shortcuts alongside the trait methods; the tradeoff is that consumers need to understand Rust’s trait bound system to use it effectively, but this is standard for the idiomatic-generics niche the crate targets, and 131 contributors plus near-universal adoption across the Rust numeric ecosystem indicate the design has held up well over nearly a decade.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers