multitype/
lib.rs

1// Copyright 2025 Gabriel Bjørnager Jensen.
2
3#![doc(html_logo_url = "https://gitlab.com/bjoernager/multitype/-/raw/master/doc-icon.svg")]
4
5//! MultiType is a crate for generalising fundamental types via traits.
6//!
7//! MultiType provideds traits such as [`Uint`](num::Uint) and [`Float`](num::Float) traits to abstract over a set of equivalent primitive types.
8//! These traits are intended to provide one-to-one copies of the interfaces that the primitive types define.
9//!
10//! # Arithmetic types
11//!
12//! MultiType defines different traits for generalising arithmetic types:
13//!
14//! * [`Uint`](num::Uint) for [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], and [`usize`];
15//! * [`Int`](num::Int) for [`i8`], [`i16`], [`i32`], [`i64`], [`i128`], and [`isize`];
16//! * [`Float`](num::Float) for [`f16`], [`f32`], [`f64`], and [`f128`].
17//!
18#![cfg_attr(feature = "std", doc = "Furthermore, `StdFloat` extends the `Float` trait with functionality that is typically only available in `std`'s floating-point types.")]
19//!
20//! ## Sized, arithmetic types
21//!
22//! The basic, arithmetic traits guarantee a minimum size that is equivalent to the smallest member of its group, e.g. `Uint` is at least `u8` and `Float` is at least `f16`.
23//!
24//! Additionally, these three arithmetic traits have subtraits that guarantee wider types, for example:
25//!
26//! * `i16` and up implement [`IntLeast16`](num::IntLeast16);
27//! * `i32` and up implement [`IntLeast32`](num::IntLeast32);
28//! * Etc.
29//!
30//! The complete list of arithmetic traits is thus:
31//!
32//! * [`Uint`](num::Uint)
33//!   * [`UintLeast16`](num::UintLeast16)
34//!   * [`UintLeast32`](num::UintLeast32)
35//!   * [`UintLeast64`](num::UintLeast64)
36//!   * [`UintLeast128`](num::UintLeast128)
37//! * [`Int`](num::Int)
38//!   * [`IntLeast16`](num::IntLeast16)
39//!   * [`IntLeast32`](num::IntLeast32)
40//!   * [`IntLeast64`](num::IntLeast64)
41//!   * [`IntLeast128`](num::IntLeast128)
42//! * [`Float`](num::Float)
43#![cfg_attr(feature = "std", doc = "  * [`StdFloat`](num::StdFloat)")]
44//!   * [`FloatLeast32`](num::FloatLeast32)
45//!   * [`FloatLeast64`](num::FloatLeast64)
46//!   * [`FloatLeast128`](num::FloatLeast128)
47//!
48//! # Array types
49//!
50//! MultiType also provides the [`Array`](array::Array) trait for generalising array types – most often over their length.
51//!
52//! An example of this trait's usecase is actually in this crate:
53//! Take, for instance, the definition of [`Uint`](num::Uint): It has a `Bytes` associated type that is used by the bytewise constructors and destructors:
54//!
55//! ```rust
56//! pub unsafe trait Uint: /* .. */ {
57//!     type Bytes;
58//!
59//!     fn from_ne_bytes(bytes: Self::Bytes) -> Self;
60//!
61//!     fn to_ne_bytes(self) -> Self::Bytes;
62//!
63//!     // ..
64//! }
65//! ```
66//!
67//! Now, anyone that would want to use the output of [`to_ne_bytes`](num::Uint::to_ne_bytes) wouldn't really have that many choices with regard to what to do with it.
68//! So, MultiType defines the `Array` trait:
69//!
70//! ```rust
71//! use multitype::array::Array;
72//!
73//! pub unsafe trait Uint: /* .. */ {
74//!     type Bytes: Array<Scalar = u8>;
75//!
76//!     // ..
77//! }
78//! ```
79//!
80//! With it, it's possible for users to generically use `Uint::to_ne_bytes` as an array type through the trait methods.
81//!
82//! # Examples
83//!
84//! A generic Fibonacci sequence:
85//!
86//! ```rust
87//! use multitype::num::Uint;
88//!
89//! fn f<T: Uint>(x: T) -> T {
90//!     let mut y    = T::from_u8(0x0);
91//!     let mut y_m1 = T::from_u8(0x0);
92//!     let mut y_m2 = T::from_u8(0x1);
93//!
94//!     let mut i = T::from_u8(0x0);
95//!     while i < x {
96//!         y = y_m1 + y_m2;
97//!
98//!         y_m2 = y_m1;
99//!         y_m1 = y;
100//!
101//!         i += T::from_u8(0x1);
102//!     }
103//!
104//!     y
105//! }
106//!
107//! assert_eq!(f(0u8),   0);
108//! assert_eq!(f(1u8),   1);
109//!
110//! assert_eq!(f(2u16),  1);
111//! assert_eq!(f(3u16),  2);
112//!
113//! assert_eq!(f(4u32),  3);
114//! assert_eq!(f(5u32),  5);
115//!
116//! assert_eq!(f(6u64),  8);
117//! assert_eq!(f(7u64), 13);
118//! ```
119//!
120//! Generic array indexing:
121//!
122//! ```rust
123//! use core::f32;
124//! use multitype::array::Array;
125//! use multitype::num::Float;
126//!
127//! fn complicated_neg<T: Float>(value: T) -> T {
128//!     let mut bytes = value.to_le_bytes();
129//!
130//!     // Invert the sign bit -- which is always the most
131//!     // significant bit of the most significant byte.
132//!     *bytes.as_mut_slice().last_mut().unwrap() ^= 0b10000000;
133//!
134//!     T::from_le_bytes(bytes)
135//! }
136//!
137//! assert_eq!(complicated_neg( 1.0f64), -1.0f64);
138//! assert_eq!(complicated_neg(-1.0f64),  1.0f64);
139//!
140//! assert_eq!(complicated_neg(f32::NEG_INFINITY), f32::INFINITY);
141//! ```
142//!
143//! # Copyright & Licence.
144//!
145//! Copyright &#169; 2025 Gabriel Bjørnager Jensen.
146//!
147//! MultiType is distributed under either an MIT licence (see `LICENCE-MIT`) or version 2.0 of the Apache License (see `LICENCE-APACHE`), at your option.
148
149#![no_std]
150
151#![cfg_attr(feature = "f16",           feature(f16))]
152#![cfg_attr(feature = "f128",          feature(f128))]
153#![cfg_attr(feature = "unstable-docs", feature(doc_cfg, intra_doc_pointers))]
154
155extern crate self as multitype;
156
157#[cfg(feature = "alloc")]
158extern crate alloc;
159
160#[cfg(feature = "std")]
161extern crate std;
162
163pub mod array;
164pub mod num;
165pub mod ptr;