Skip to main content

Crate numlike

Crate numlike 

Source
Expand description

Repository Docs Crates.io MIT OR Apache 2.0

§numlike

Numeric traits for generic mathematics. More fine-grained, less restrictive and less conservative alternative to num-traits.

This crate has no unsafe code and no mandatory third-party dependencies, and is no_std-compatible. Most of no_std operations on floating point numbers still have a dependency on libm, which is gated behind libm feature flag.

§Usage

§Adding dependency

[dependencies]
numlike = { version = "0.1.5" }

§Comparison to other libraries

§Why numlike and not num-traits?

We developed numlike primarily because we disagree with many of design decisions in the venerable num-traits crate.

  • num-traits’s Zero and One traits require Add and Mul traits, respectively, to be implemented. This makes it impossible to distinguish a 0 for algebraic structures that don’t implement addition (e.g. absorption magma and absorption monoid, aka. magma with zero and monoid with zero, where 0 is merely the absorbing element). Likewise, 1 can’t be distinguished with num-traits when there is no multiplication (e.g. because a naive implementation of multiplication for all elements would be inefficient, or because 1 is merely the generating element (aka. generator)).
    • num-traits also requires Output = Self for Add and Mul, making it impossible to use Zero and One for statically-typed unit of measurement libraries like uom.
      • numlike does not have these problems because it does not have any supertraits for its Zero and One.
    • Moreover, num-traits’s Zero and One do not provide ZERO and ONE associated constants, but instead return them from ::zero() and ::one() functions. These constants were only later added through new separate traits, ConstZero and ConstOne, presumably to avoid breaking changes.
      • numlike’s Zero and One provide ZERO and ONE associated constants directly.
  • num-traits’s Bounded trait only returns finite minimum and maximum values. This makes no difference for integers, but e.g. for floats .max_value() returns f32::MAX, which is actually the largest finite number, equal to 3.40282347e+38, not the positive infinity. num-traits has no interface to generically obtain negative or positive infinity as min. or max. value.
    • numlike solves that by providing MinExtended/ MaxExtended traits that result in negative and positive infinities for floats, and MinFinite/ MaxFinite traits that give only finite values just as above num-traits’s Bounded does.
  • num-traits provides .signum() and .abs() methods only for types implementing Signed trait, which excludes unsigned integer types.
    • But having these methods generically for both signed and unsigned types can be useful for finding canonical denominators, reducing fractions, combining and simplifying radicals, so numlike provides these methods through two decoupled traits, Signum and Abs, implemented for all numeric primitives.
  • num-traits does not provide checked mathematical operation traits, CheckedAdd, CheckedSub, CheckedMul, CheckedDiv, CheckedNeg, CheckedRem, for floats.
    • numlike implements its own versions of these traits for all numeric primitives.
  • Developers of num-traits seem to avoid breaking changes, strongly preferring to create new traits instead of making modifications to existing ones. This provides stability for users, but prevents at least some of the above issues from being solved.
    • Because of that, we have decided to roll our own library (this crate). However, because it’s in active development, we are lacking the stability of num-traits – we are much more likely to have breaking changes and bugs.
  • Furthermore, numlike also has its own features, such as:
    • Equality and order traits that fix NaNs to be the highest value in the set, even larger than positive infinity, allowing for total order: NanfixPartialEq, NanfixEq, NanmaxPartialOrd, NanmaxOrd, NanminPartialOrd, NanminOrd.
      • But if you want core::cmp traits instead, consider using ordered-float crate’s OrderedFloat float type wrapper instead. This is obviously often the better choice, because core::cmp traits will work with a much larger number of existing libraries and have Rust’s syntactic sugar.

§Feature flags

  • std (enabled by default) — Disable for no_std compatibility.
  • libm — Use libm to implement some operations if std is disabled.

Modules§

bytes
cmp
elem
fns
limits
ops