Lines
100 %
Functions
Branches
//! **Development in progress**
//!
//! Type-level rational numbers based on [typenum].
//! [typenum]: https://crates.io/crates/typenum
#![no_std]
#![cfg_attr(test, recursion_limit = "256")]
use core::marker::PhantomData;
use typenum::Gcd;
#[doc(no_inline)]
pub use typenum::consts::*;
pub use typenum::{Equal, Greater, Less, NInt, PInt};
mod uint;
pub use uint::NonZeroUnsigned;
mod int;
pub use int::Integer;
mod marker;
pub use marker::{NonNegative, NonZero, NotOne};
/// Type-level integers usable as denominators of type-level rational numbers.
///
/// # Examples
/// ```
/// use typerat::*;
/// fn is_denominator<D: Denominator>() -> bool {
/// true
/// }
/// assert!(is_denominator::<P1>());
/// assert!(is_denominator::<P2>());
/// ```compile_fail
/// # use typerat::*;
/// #
/// # fn is_denominator<D: Denominator>() -> bool {
/// # true
/// # }
/// assert!(is_denominator::<Z0>());
/// assert!(is_denominator::<N1>());
pub trait Denominator: Integer + NonNegative + NonZero {}
impl<D> Denominator for D where D: Integer + NonNegative + NonZero {}
/// Type-level integers usable as numerators of type-level rational numbers with denominator `D`.
/// fn is_numerator_for_denominator_2<N: Numerator<P2>>() -> bool {
/// assert!(is_numerator_for_denominator_2::<P1>());
/// assert!(is_numerator_for_denominator_2::<N1>());
/// assert!(is_numerator_for_denominator_2::<P3>());
/// assert!(is_numerator_for_denominator_2::<N3>());
/// # fn is_numerator_for_denominator_2<N: Numerator<P2>>() -> bool {
/// assert!(is_numerator_for_denominator_2::<P2>());
/// assert!(is_numerator_for_denominator_2::<N2>());
/// assert!(is_numerator_for_denominator_2::<P4>());
pub trait Numerator<D = P1>: Integer + Gcd<D, Output = P1> {}
impl<N, D> Numerator<D> for N
where
N: Integer + Gcd<D, Output = P1>,
D: Denominator,
{
}
/// `Q<N, D>` represents a type-level rational number with numerator `N` and denominator `D`.
#[derive(Debug)]
pub struct Q<N, D = P1>(PhantomData<(N, D)>)
N: Numerator<D>,
D: Denominator;
impl<N, D> Q<N, D>
const SELF: Self = Q(PhantomData);
/// Constructs a new instance of this type-level rational number.
pub const fn new() -> Self {
Self::SELF
/// Borrows an instance of this type-level rational number.
pub const fn borrow<'a>() -> &'a Self {
&Self::SELF
impl<N, D> Clone for Q<N, D>
fn clone(&self) -> Self {
*self
impl<N, D> Copy for Q<N, D>
impl<N, D> Default for Q<N, D>
fn default() -> Self {
Self::new()
mod rational;
pub use rational::Rational;
mod ops;
pub use ops::Recip;
mod cmp;
pub use cmp::{Cmp, Ordering};
mod fmt;
#[cfg(test)]
mod tests {
use super::*;
use char_buf::CharBuf;
use core::fmt::Write;
macro_rules! format {
($($arg:tt)*) => {
let mut w = CharBuf::<1024>::new();
write!(w, $($arg)*).unwrap();
w
};
#[test]
fn test_q() {
let a = Q::<P1, P2>::default();
let b = a.clone();
let c: PhantomData<(P1, P2)> = PhantomData;
let d = Q::<P1, P2>::borrow();
assert_eq!(a, b);
assert_eq!(&a, d);
assert_eq!(format!("{:?}", a), format!("Q({:?})", c));