sht_colour/lib.rs
1#![doc = include_str!("../README.md")]
2
3#![warn(missing_docs)]
4#![warn(clippy::all)]
5#![warn(clippy::missing_docs_in_private_items)]
6
7
8use ::num::{checked_pow, CheckedMul, Integer, Unsigned};
9
10/// Re-export from `num` crate, represents the ratio between two numbers.
11pub use ::num::rational::Ratio;
12pub use sht::{ChannelRatios, ColourChannel, SecondaryColour, SHT};
13
14/// Support for RGB colour codes in hex format.
15pub mod rgb;
16/// Support for SHT colour codes in SHT format.
17pub mod sht;
18
19#[cfg(test)]
20mod lib_tests;
21
22/// Round a ratio to a simpler approximation, in a given base.
23///
24/// # Arguments
25/// * `ratio_on_unit_interval` - A [`Ratio<T>`] between 0 and 1 inclusive, which
26/// will be rounded to a certain precision.
27/// * `base` - The number base to round within.
28/// * `exponent` - How many digits in that base to preserve.
29/// * `negative_offset` - Usually 0. If 1, then subtract one from the
30/// exponentiated base. Useful for hex codes because they are interpreted as a
31/// fraction over 0xFF rather than over 0x100, meaning they have one less
32/// representable value than normal.
33///
34/// # Panics
35/// Will panic if the exponentiation overflows the integer type.
36///
37/// [`Ratio<T>`]: num::rational::Ratio
38fn round_denominator<T>(
39 ratio_on_unit_interval: Ratio<T>,
40 base: T,
41 exponent: usize,
42 negative_offset: T,
43) -> Ratio<T>
44where
45 T: Integer + Unsigned + CheckedMul + Clone + From<u8>,
46{
47 let half = Ratio::new(1.into(), 2.into());
48 let new_denominator =
49 checked_pow(base, exponent).expect("Overflow calculating denominator") - negative_offset;
50 ((ratio_on_unit_interval * new_denominator.clone() + half).trunc()) / new_denominator
51}