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#")]
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 © 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;