num_irrational/
traits.rs

1use num_rational::Ratio;
2
3#[cfg(feature = "num-bigint")]
4use num_bigint::{BigInt, BigUint};
5
6/// Represents a possible error occured calling [FromSqrt]
7#[derive(Clone, Debug, PartialEq)]
8pub struct FromSqrtError<T> {
9    pub data: T,
10    pub kind: SqrtErrorKind,
11}
12
13/// Types of [FromSqrt] errors
14#[derive(Copy, Clone, Debug, PartialEq)]
15pub enum SqrtErrorKind {
16    /// A proper representation will requires a integer type with more capacity
17    Overflow,
18    /// The square root is a complex number
19    Complex,
20    /// The square root of the target cannot be represented as a quadratic surd
21    Unrepresentable,
22}
23
24/// Create a number instance from the square root of another number.
25///
26/// In case there are multiple solution for square root,
27/// only canonical result will be returned
28pub trait FromSqrt<T>: Sized {
29    fn from_sqrt(t: T) -> Result<Self, FromSqrtError<T>>;
30}
31
32/// Represents a number conversion with probably exact value.
33#[derive(PartialEq, Debug)]
34pub enum Approximation<T> {
35    Approximated(T),
36    Exact(T),
37}
38
39impl<T> Approximation<T> {
40    /// Get the computed value regardless of whether it's exact
41    pub fn value(self) -> T {
42        match self {
43            Approximation::Approximated(v) => v,
44            Approximation::Exact(v) => v,
45        }
46    }
47}
48
49// XXX: backport into num-traits (https://github.com/rust-num/num-rational/issues/100)
50/// This trait represents a real number that is computable.
51/// See [Wiki](https://en.wikipedia.org/wiki/Computable_number)
52pub trait Computable<T> {
53    /// Return an approximated rational representation of the number
54    /// The `limit` argument specify the maximum value of denominator. This will
55    /// ensures the error of the approximation is less than 1/limit^2.
56    fn approximated(&self, limit: &T) -> Approximation<Ratio<T>>;
57}
58
59// TODO: implement the rational approximation for all irrational types
60
61/// Represents a number type with corresponding signed version
62///
63/// Signed number can implement this trait as well, with `type Signed = Self`.
64pub trait WithSigned {
65    type Signed;
66    fn to_signed(self) -> Self::Signed;
67}
68
69/// Represents a number type with corresponding unsigned version
70///
71/// Unsigned number can implement this trait as well, with `type Unsigned = Self`.
72pub trait WithUnsigned {
73    type Unsigned;
74    fn to_unsigned(self) -> Self::Unsigned;
75}
76
77macro_rules! impl_primitive_sign {
78    ($TSigned:ty, $TUnsigned:ty) => {
79        impl WithSigned for $TUnsigned {
80            type Signed = $TSigned;
81            #[inline]
82            fn to_signed(self) -> Self::Signed {
83                self as $TSigned
84            }
85        }
86        impl WithSigned for $TSigned {
87            type Signed = $TSigned;
88            #[inline]
89            fn to_signed(self) -> Self {
90                self
91            }
92        }
93        impl WithUnsigned for $TSigned {
94            type Unsigned = $TUnsigned;
95            #[inline]
96            fn to_unsigned(self) -> Self::Unsigned {
97                self as $TUnsigned
98            }
99        }
100        impl WithUnsigned for $TUnsigned {
101            type Unsigned = $TUnsigned;
102            #[inline]
103            fn to_unsigned(self) -> Self {
104                self
105            }
106        }
107    };
108}
109impl_primitive_sign!(i8, u8);
110impl_primitive_sign!(i16, u16);
111impl_primitive_sign!(i32, u32);
112impl_primitive_sign!(i64, u64);
113impl_primitive_sign!(i128, u128);
114
115#[cfg(feature = "num-bigint")]
116impl WithSigned for BigUint {
117    type Signed = BigInt;
118    #[inline]
119    fn to_signed(self) -> Self::Signed {
120        BigInt::from(self)
121    }
122}
123
124#[cfg(feature = "num-bigint")]
125impl WithUnsigned for BigUint {
126    type Unsigned = BigUint;
127    #[inline]
128    fn to_unsigned(self) -> Self {
129        self
130    }
131}
132
133#[cfg(feature = "num-bigint")]
134impl WithUnsigned for BigInt {
135    type Unsigned = BigUint;
136    #[inline]
137    fn to_unsigned(self) -> Self::Unsigned {
138        self.to_biguint().unwrap()
139    }
140}
141
142#[cfg(feature = "num-bigint")]
143impl WithSigned for BigInt {
144    type Signed = BigInt;
145    #[inline]
146    fn to_signed(self) -> Self::Signed {
147        self
148    }
149}