lineic/
lib.rs

1//! # lineic - Flexible linear interpolator for Rust
2//!
3//! [![Crates.io](https://img.shields.io/crates/v/lineic.svg)](https://crates.io/crates/lineic/)
4//! [![Build Status](https://github.com/rscarson/lineic/actions/workflows/tests.yml/badge.svg?branch=master)](https://github.com/rscarson/lineic/actions?query=branch%3Amaster)
5//! [![docs.rs](https://img.shields.io/docsrs/lineic)](https://docs.rs/lineic/latest/)
6//! [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://raw.githubusercontent.com/rscarson/lineic/master/LICENSE)
7//!
8//! This library provides a simple way to interpolate between values across a range.  
9//! It supports N-dimensional values, mixed types, and interpolation across any number of data sets.
10//!
11//! Inverted ranges work fine, and out of range values are clamped to the provided range.
12//!
13//! The library is designed to be simple to use, and as flexible as possible;  
14//! For use with non-standard types, the library provides a `Numeric` trait that can be implemented.
15//!
16//! The library also provides a `no_std` feature for use in embedded systems.  
17//! **Warning: The `no_std` feature disables the `LinearInterpolator` struct which enables interpolation across >2 data sets**
18//!
19//! ## Examples
20//!
21//! The simplest possible use of the library is mapping one range to another  
22//! Here we can map values in the range `0.0..=10.0` to the range `30.0..=35.0`
23//! ```rust
24//! use lineic::interpolators::F32InterpolationBucket;
25//! let interpolator = F32InterpolationBucket::new(0.0..=10.0, [30.0], [35.0]);
26//! assert_eq!(interpolator.interpolate(5.0), [32.5]);
27//! ```
28//!
29//! `lineic::interpolators::F32InterpolationBucket` here is a type alias for `lineic::InterpolationBucket<1, f32, f32>`  
30//! The `interpolators` module defines a set of type aliases for common same-type numeric interpolators.
31//!
32//! -----
33//!
34//! The target does not have to be a single value - here we interpolate across a pair of RGB values  
35//! The result is a smooth gradient from `red` to `green` for values in the range `0.0..=10.0`
36//! ```rust
37//! use lineic::interpolators::F32InterpolationBucket;
38//! let interpolator = F32InterpolationBucket::new(0.0..=10.0, [255.0, 0.0, 0.0], [0.0, 255.0, 0.0]);
39//! assert_eq!(interpolator.interpolate(5.0), [127.5, 127.5, 0.0]);
40//! ```
41//!
42//! -----
43//!
44//! The library can also interpolate smoothly across multiple pairs of values  
45//! This example forms a sort of traffic light sequence, interpolating between `red`, `yellow`, and `green`
46//!
47//! The range is reversed here to demonstrate that the library can handle that
48//!
49//! ```rust
50//! use lineic::interpolators::F32LinearInterpolator;
51//! ;
52//! let interpolator = F32LinearInterpolator::new(
53//!     10.0..=0.0,
54//!     &[[0.0, 255.0, 0.0], [255.0, 255.0, 0.0], [255.0, 0.0, 0.0]],
55//! );
56//! assert_eq!(interpolator.interpolate(5.0), [255.0, 255.0, 0.0]);
57//! assert_eq!(interpolator.interpolate(0.0), [255.0, 0.0, 0.0]);
58//! ```
59//!
60//! -----
61//!
62//! The types for the range and values do not need to the same  
63//! Here a `f64` range is used to interpolate across `u8` values
64//! ```rust
65//! use lineic::LinearInterpolator;
66//!
67//! let interpolator: LinearInterpolator<'_, 3, f64, u8> =
68//!     LinearInterpolator::new(0.0..=10.0, &[[0, 255, 0], [255, 255, 0], [255, 0, 0]]);
69//!
70//! assert_eq!(interpolator.interpolate(5.0), [255, 255, 0]);
71//! assert_eq!(interpolator.interpolate(0.0), [0, 255, 0]);
72//! ```
73//!
74//! By default, you can interpolate across the following types:
75//! - `f32` `f64`
76//! - `i8` `i16` `i32` `i64` `i128` `isize`
77//! - `u8` `u16` `u32` `u64` `u128` `usize`
78//!
79//! For other types, you can implement the `Numeric` trait.  
80//! See `examples/custom_types.rs` for an example of how to do this.
81//!
82#![cfg_attr(feature = "no_std", no_std)]
83#![warn(missing_docs)]
84#![warn(clippy::pedantic)]
85#![allow(clippy::module_name_repetitions)] // Module's are not being exported so they are not being repeated
86
87mod bucket;
88pub use bucket::InterpolationBucket;
89
90mod range;
91pub use range::ReversibleRange;
92
93#[cfg(not(feature = "no_std"))]
94mod interpolator;
95#[cfg(not(feature = "no_std"))]
96pub use interpolator::LinearInterpolator;
97
98mod number;
99pub use number::Numeric;
100
101/// This module contains a set of same-type interpolator type aliases for common numeric types.
102pub mod interpolators {
103    use crate::InterpolationBucket;
104
105    #[cfg(not(feature = "no_std"))]
106    use crate::LinearInterpolator;
107
108    /// Interpolation bucket mapping f64 ranges to f64 values
109    /// For more information, see [`InterpolationBucket`]
110    pub type F64InterpolationBucket<const N: usize> = InterpolationBucket<N, f64, f64>;
111
112    /// Linear interpolator for f64 values
113    /// For more information, see [`LinearInterpolator`]
114    #[cfg(not(feature = "no_std"))]
115    pub type F64LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, f64, f64>;
116
117    /// Interpolation bucket mapping f32 ranges to f32 values
118    /// For more information, see [`InterpolationBucket`]
119    pub type F32InterpolationBucket<const N: usize> = InterpolationBucket<N, f32, f32>;
120
121    /// Linear interpolator for f32 values
122    /// For more information, see [`LinearInterpolator`]
123    #[cfg(not(feature = "no_std"))]
124    pub type F32LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, f32, f32>;
125
126    /// Interpolation bucket mapping i128 ranges to i128 values
127    /// For more information, see [`InterpolationBucket`]
128    pub type I128InterpolationBucket<const N: usize> = InterpolationBucket<N, i128, i128>;
129
130    /// Linear interpolator for i128 values
131    /// For more information, see [`LinearInterpolator`]
132    #[cfg(not(feature = "no_std"))]
133    pub type I128LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, i128, i128>;
134
135    /// Interpolation bucket mapping i64 ranges to i64 values
136    /// For more information, see [`InterpolationBucket`]
137    pub type I64InterpolationBucket<const N: usize> = InterpolationBucket<N, i64, i64>;
138
139    /// Linear interpolator for i64 values
140    /// For more information, see [`LinearInterpolator`]
141    #[cfg(not(feature = "no_std"))]
142    pub type I64LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, i64, i64>;
143
144    /// Interpolation bucket mapping i32 ranges to i32 values
145    /// For more information, see [`InterpolationBucket`]
146    pub type I32InterpolationBucket<const N: usize> = InterpolationBucket<N, i32, i32>;
147
148    /// Linear interpolator for i32 values
149    /// For more information, see [`LinearInterpolator`]
150    #[cfg(not(feature = "no_std"))]
151    pub type I32LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, i32, i32>;
152
153    /// Interpolation bucket mapping i16 ranges to i16 values
154    /// For more information, see [`InterpolationBucket`]
155    pub type I16InterpolationBucket<const N: usize> = InterpolationBucket<N, i16, i16>;
156
157    /// Linear interpolator for i16 values
158    /// For more information, see [`LinearInterpolator`]
159    #[cfg(not(feature = "no_std"))]
160    pub type I16LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, i16, i16>;
161
162    /// Interpolation bucket mapping i8 ranges to i8 values
163    /// For more information, see [`InterpolationBucket`]
164    pub type I8InterpolationBucket<const N: usize> = InterpolationBucket<N, i8, i8>;
165
166    /// Linear interpolator for i8 values
167    /// For more information, see [`LinearInterpolator`]
168    #[cfg(not(feature = "no_std"))]
169    pub type I8LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, i8, i8>;
170
171    /// Interpolation bucket mapping isize ranges to isize values
172    /// For more information, see [`InterpolationBucket`]
173    pub type ISizeInterpolationBucket<const N: usize> = InterpolationBucket<N, isize, isize>;
174
175    /// Linear interpolator for isize values
176    /// For more information, see [`LinearInterpolator`]
177    #[cfg(not(feature = "no_std"))]
178    pub type ISizeLinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, isize, isize>;
179
180    /// Interpolation bucket mapping u128 ranges to u128 values
181    /// For more information, see [`InterpolationBucket`]
182    pub type U128InterpolationBucket<const N: usize> = InterpolationBucket<N, u128, u128>;
183
184    /// Linear interpolator for u128 values
185    /// For more information, see [`LinearInterpolator`]
186    #[cfg(not(feature = "no_std"))]
187    pub type U128LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, u128, u128>;
188
189    /// Interpolation bucket mapping u64 ranges to u64 values
190    /// For more information, see [`InterpolationBucket`]
191    pub type U64InterpolationBucket<const N: usize> = InterpolationBucket<N, u64, u64>;
192
193    /// Linear interpolator for u64 values
194    /// For more information, see [`LinearInterpolator`]
195    #[cfg(not(feature = "no_std"))]
196    pub type U64LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, u64, u64>;
197
198    /// Interpolation bucket mapping u32 ranges to u32 values
199    /// For more information, see [`InterpolationBucket`]
200    pub type U32InterpolationBucket<const N: usize> = InterpolationBucket<N, u32, u32>;
201
202    /// Linear interpolator for u32 values
203    /// For more information, see [`LinearInterpolator`]
204    #[cfg(not(feature = "no_std"))]
205    pub type U32LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, u32, u32>;
206
207    /// Interpolation bucket mapping u16 ranges to u16 values
208    /// For more information, see [`InterpolationBucket`]
209    pub type U16InterpolationBucket<const N: usize> = InterpolationBucket<N, u16, u16>;
210
211    /// Linear interpolator for u16 values
212    /// For more information, see [`LinearInterpolator`]
213    #[cfg(not(feature = "no_std"))]
214    pub type U16LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, u16, u16>;
215
216    /// Interpolation bucket mapping u8 ranges to u8 values
217    /// For more information, see [`InterpolationBucket`]
218    pub type U8InterpolationBucket<const N: usize> = InterpolationBucket<N, u8, u8>;
219
220    /// Linear interpolator for u8 values
221    /// For more information, see [`LinearInterpolator`]
222    #[cfg(not(feature = "no_std"))]
223    pub type U8LinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, u8, u8>;
224
225    /// Interpolation bucket mapping usize ranges to usize values
226    /// For more information, see [`InterpolationBucket`]
227    pub type USizeInterpolationBucket<const N: usize> = InterpolationBucket<N, usize, usize>;
228
229    /// Linear interpolator for usize values
230    /// For more information, see [`LinearInterpolator`]
231    #[cfg(not(feature = "no_std"))]
232    pub type USizeLinearInterpolator<'a, const N: usize> = LinearInterpolator<'a, N, usize, usize>;
233}