typenum/
type_operators.rs

1//! Useful **type operators** that are not defined in `core::ops`.
2
3use crate::{
4    private::{Internal, InternalMarker},
5    Bit, NInt, NonZero, PInt, UInt, UTerm, Unsigned, Z0,
6};
7
8/// A **type operator** that ensures that `Rhs` is the same as `Self`, it is mainly useful
9/// for writing macros that can take arbitrary binary or unary operators.
10///
11/// `Same` is implemented generically for all types; it should never need to be implemented
12/// for anything else.
13///
14/// Note that Rust lazily evaluates types, so this will only fail for two different types if
15/// the `Output` is used.
16///
17/// # Example
18/// ```rust
19/// use typenum::{Same, Unsigned, U4, U5};
20///
21/// assert_eq!(<U5 as Same<U5>>::Output::to_u32(), 5);
22///
23/// // Only an error if we use it:
24/// # #[allow(dead_code)]
25/// type Undefined = <U5 as Same<U4>>::Output;
26/// // Compiler error:
27/// // Undefined::to_u32();
28/// ```
29pub trait Same<Rhs = Self> {
30    /// Should always be `Self`
31    type Output;
32}
33
34impl<T> Same<T> for T {
35    type Output = T;
36}
37
38/// A **type operator** that returns the absolute value.
39///
40/// # Example
41/// ```rust
42/// use typenum::{Abs, Integer, N5};
43///
44/// assert_eq!(<N5 as Abs>::Output::to_i32(), 5);
45/// ```
46pub trait Abs {
47    /// The absolute value.
48    type Output;
49}
50
51impl Abs for Z0 {
52    type Output = Z0;
53}
54
55impl<U: Unsigned + NonZero> Abs for PInt<U> {
56    type Output = Self;
57}
58
59impl<U: Unsigned + NonZero> Abs for NInt<U> {
60    type Output = PInt<U>;
61}
62
63/// A **type operator** that provides exponentiation by repeated squaring.
64///
65/// # Example
66/// ```rust
67/// use typenum::{Integer, Pow, N3, P3};
68///
69/// assert_eq!(<N3 as Pow<P3>>::Output::to_i32(), -27);
70/// ```
71pub trait Pow<Exp> {
72    /// The result of the exponentiation.
73    type Output;
74    /// This function isn't used in this crate, but may be useful for others.
75    /// It is implemented for primitives.
76    ///
77    /// # Example
78    /// ```rust
79    /// use typenum::{Pow, U3};
80    ///
81    /// let a = 7u32.powi(U3::new());
82    /// let b = 7u32.pow(3);
83    /// assert_eq!(a, b);
84    ///
85    /// let x = 3.0.powi(U3::new());
86    /// let y = 27.0;
87    /// assert_eq!(x, y);
88    /// ```
89    fn powi(self, exp: Exp) -> Self::Output;
90}
91
92macro_rules! impl_pow_f {
93    ($t:ty) => {
94        impl Pow<UTerm> for $t {
95            type Output = $t;
96            #[inline]
97            fn powi(self, _: UTerm) -> Self::Output {
98                1.0
99            }
100        }
101
102        impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t {
103            type Output = $t;
104            // powi is unstable in core, so we have to write this function ourselves.
105            // copied from num::pow::pow
106            #[inline]
107            fn powi(self, _: UInt<U, B>) -> Self::Output {
108                let mut exp = <UInt<U, B> as Unsigned>::to_u32();
109                let mut base = self;
110
111                if exp == 0 {
112                    return 1.0;
113                }
114
115                while exp & 1 == 0 {
116                    base *= base;
117                    exp >>= 1;
118                }
119                if exp == 1 {
120                    return base;
121                }
122
123                let mut acc = base.clone();
124                while exp > 1 {
125                    exp >>= 1;
126                    base *= base;
127                    if exp & 1 == 1 {
128                        acc *= base.clone();
129                    }
130                }
131                acc
132            }
133        }
134
135        impl Pow<Z0> for $t {
136            type Output = $t;
137            #[inline]
138            fn powi(self, _: Z0) -> Self::Output {
139                1.0
140            }
141        }
142
143        impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t {
144            type Output = $t;
145            // powi is unstable in core, so we have to write this function ourselves.
146            // copied from num::pow::pow
147            #[inline]
148            fn powi(self, _: PInt<U>) -> Self::Output {
149                let mut exp = U::to_u32();
150                let mut base = self;
151
152                if exp == 0 {
153                    return 1.0;
154                }
155
156                while exp & 1 == 0 {
157                    base *= base;
158                    exp >>= 1;
159                }
160                if exp == 1 {
161                    return base;
162                }
163
164                let mut acc = base.clone();
165                while exp > 1 {
166                    exp >>= 1;
167                    base *= base;
168                    if exp & 1 == 1 {
169                        acc *= base.clone();
170                    }
171                }
172                acc
173            }
174        }
175
176        impl<U: Unsigned + NonZero> Pow<NInt<U>> for $t {
177            type Output = $t;
178
179            #[inline]
180            fn powi(self, _: NInt<U>) -> Self::Output {
181                <$t as Pow<PInt<U>>>::powi(self, PInt::new()).recip()
182            }
183        }
184    };
185}
186
187impl_pow_f!(f32);
188impl_pow_f!(f64);
189
190macro_rules! impl_pow_i {
191    () => ();
192    ($(#[$meta:meta])*  $t: ty $(, $tail:tt)*) => (
193        $(#[$meta])*
194        impl Pow<UTerm> for $t {
195            type Output = $t;
196            #[inline]
197            fn powi(self, _: UTerm) -> Self::Output {
198                1
199            }
200        }
201
202        $(#[$meta])*
203        impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t {
204            type Output = $t;
205            #[inline]
206            fn powi(self, _: UInt<U, B>) -> Self::Output {
207                self.pow(<UInt<U, B> as Unsigned>::to_u32())
208            }
209        }
210
211        $(#[$meta])*
212        impl Pow<Z0> for $t {
213            type Output = $t;
214            #[inline]
215            fn powi(self, _: Z0) -> Self::Output {
216                1
217            }
218        }
219
220        $(#[$meta])*
221        impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t {
222            type Output = $t;
223            #[inline]
224            fn powi(self, _: PInt<U>) -> Self::Output {
225                self.pow(U::to_u32())
226            }
227        }
228
229        impl_pow_i!($($tail),*);
230    );
231}
232
233impl_pow_i!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
234#[cfg(feature = "i128")]
235impl_pow_i!(
236    #[cfg_attr(docsrs, doc(cfg(feature = "i128")))]
237    u128,
238    i128
239);
240
241#[test]
242fn pow_test() {
243    use crate::consts::*;
244    let z0 = Z0::new();
245    let p3 = P3::new();
246
247    let u0 = U0::new();
248    let u3 = U3::new();
249    let n3 = N3::new();
250
251    macro_rules! check {
252        ($x:ident) => {
253            assert_eq!($x.powi(z0), 1);
254            assert_eq!($x.powi(u0), 1);
255
256            assert_eq!($x.powi(p3), $x * $x * $x);
257            assert_eq!($x.powi(u3), $x * $x * $x);
258        };
259        ($x:ident, $f:ident) => {
260            assert!((<$f as Pow<Z0>>::powi(*$x, z0) - 1.0).abs() < ::core::$f::EPSILON);
261            assert!((<$f as Pow<U0>>::powi(*$x, u0) - 1.0).abs() < ::core::$f::EPSILON);
262
263            assert!((<$f as Pow<P3>>::powi(*$x, p3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
264            assert!((<$f as Pow<U3>>::powi(*$x, u3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
265
266            if *$x == 0.0 {
267                assert!(<$f as Pow<N3>>::powi(*$x, n3).is_infinite());
268            } else {
269                assert!(
270                    (<$f as Pow<N3>>::powi(*$x, n3) - 1. / $x / $x / $x).abs()
271                        < ::core::$f::EPSILON
272                );
273            }
274        };
275    }
276
277    for x in &[0i8, -3, 2] {
278        check!(x);
279    }
280    for x in &[0u8, 1, 5] {
281        check!(x);
282    }
283    for x in &[0usize, 1, 5, 40] {
284        check!(x);
285    }
286    for x in &[0isize, 1, 2, -30, -22, 48] {
287        check!(x);
288    }
289    for x in &[0.0f32, 2.2, -3.5, 378.223] {
290        check!(x, f32);
291    }
292    for x in &[0.0f64, 2.2, -3.5, -2387.2, 234.22] {
293        check!(x, f64);
294    }
295}
296
297/// A **type operator** for comparing `Self` and `Rhs`. It provides a similar functionality to
298/// the function
299/// [`core::cmp::Ord::cmp`](https://doc.rust-lang.org/nightly/core/cmp/trait.Ord.html#tymethod.cmp)
300/// but for types.
301///
302/// # Example
303/// ```rust
304/// use typenum::{Cmp, Ord, N3, P2, P5};
305/// use std::cmp::Ordering;
306///
307/// assert_eq!(<P2 as Cmp<N3>>::Output::to_ordering(), Ordering::Greater);
308/// assert_eq!(<P2 as Cmp<P2>>::Output::to_ordering(), Ordering::Equal);
309/// assert_eq!(<P2 as Cmp<P5>>::Output::to_ordering(), Ordering::Less);
310pub trait Cmp<Rhs = Self> {
311    /// The result of the comparison. It should only ever be one of `Greater`, `Less`, or `Equal`.
312    type Output;
313
314    #[doc(hidden)]
315    fn compare<IM: InternalMarker>(&self, _: &Rhs) -> Self::Output;
316}
317
318/// A **type operator** that gives the length of an `Array` or the number of bits in a `UInt`.
319#[allow(clippy::len_without_is_empty)]
320pub trait Len {
321    /// The length as a type-level unsigned integer.
322    type Output: crate::Unsigned;
323    /// This function isn't used in this crate, but may be useful for others.
324    fn len(&self) -> Self::Output;
325}
326
327/// A **type operator** that gives the sum of all elements of an `Array`.
328pub trait FoldAdd {
329    /// The type of the result of the sum
330    type Output;
331}
332
333/// A **type operator** that gives the product of all elements of an `Array`.
334pub trait FoldMul {
335    /// The type of the result of the product
336    type Output;
337}
338
339#[test]
340fn fold_test() {
341    use crate::*;
342    assert_eq!(10, <FoldSum::<tarr![U2, U3, U5]>>::to_u32());
343    assert_eq!(30, <FoldProd::<tarr![U2, U3, U5]>>::to_u32());
344}
345
346/// Division as a partial function. This **type operator** performs division just as `Div`, but is
347/// only defined when the result is an integer (i.e. there is no remainder).
348pub trait PartialDiv<Rhs = Self> {
349    /// The type of the result of the division
350    type Output;
351    /// Method for performing the division
352    fn partial_div(self, _: Rhs) -> Self::Output;
353}
354
355/// A **type operator** that returns the minimum of `Self` and `Rhs`.
356pub trait Min<Rhs = Self> {
357    /// The type of the minimum of `Self` and `Rhs`
358    type Output;
359    /// Method returning the minimum
360    fn min(self, rhs: Rhs) -> Self::Output;
361}
362
363/// A **type operator** that returns the maximum of `Self` and `Rhs`.
364pub trait Max<Rhs = Self> {
365    /// The type of the maximum of `Self` and `Rhs`
366    type Output;
367    /// Method returning the maximum
368    fn max(self, rhs: Rhs) -> Self::Output;
369}
370
371use crate::Compare;
372
373/// A **type operator** that returns `True` if `Self < Rhs`, otherwise returns `False`.
374pub trait IsLess<Rhs = Self> {
375    /// The type representing either `True` or `False`
376    type Output: Bit;
377    /// Method returning `True` or `False`.
378    #[allow(clippy::wrong_self_convention)]
379    fn is_less(self, rhs: Rhs) -> Self::Output;
380}
381
382use crate::private::IsLessPrivate;
383impl<A, B> IsLess<B> for A
384where
385    A: Cmp<B> + IsLessPrivate<B, Compare<A, B>>,
386{
387    type Output = <A as IsLessPrivate<B, Compare<A, B>>>::Output;
388
389    #[inline]
390    fn is_less(self, rhs: B) -> Self::Output {
391        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
392        self.is_less_private(rhs, lhs_cmp_rhs)
393    }
394}
395
396/// A **type operator** that returns `True` if `Self == Rhs`, otherwise returns `False`.
397pub trait IsEqual<Rhs = Self> {
398    /// The type representing either `True` or `False`
399    type Output: Bit;
400    /// Method returning `True` or `False`.
401    #[allow(clippy::wrong_self_convention)]
402    fn is_equal(self, rhs: Rhs) -> Self::Output;
403}
404
405use crate::private::IsEqualPrivate;
406impl<A, B> IsEqual<B> for A
407where
408    A: Cmp<B> + IsEqualPrivate<B, Compare<A, B>>,
409{
410    type Output = <A as IsEqualPrivate<B, Compare<A, B>>>::Output;
411
412    #[inline]
413    fn is_equal(self, rhs: B) -> Self::Output {
414        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
415        self.is_equal_private(rhs, lhs_cmp_rhs)
416    }
417}
418
419/// A **type operator** that returns `True` if `Self > Rhs`, otherwise returns `False`.
420pub trait IsGreater<Rhs = Self> {
421    /// The type representing either `True` or `False`
422    type Output: Bit;
423    /// Method returning `True` or `False`.
424    #[allow(clippy::wrong_self_convention)]
425    fn is_greater(self, rhs: Rhs) -> Self::Output;
426}
427
428use crate::private::IsGreaterPrivate;
429impl<A, B> IsGreater<B> for A
430where
431    A: Cmp<B> + IsGreaterPrivate<B, Compare<A, B>>,
432{
433    type Output = <A as IsGreaterPrivate<B, Compare<A, B>>>::Output;
434
435    #[inline]
436    fn is_greater(self, rhs: B) -> Self::Output {
437        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
438        self.is_greater_private(rhs, lhs_cmp_rhs)
439    }
440}
441
442/// A **type operator** that returns `True` if `Self <= Rhs`, otherwise returns `False`.
443pub trait IsLessOrEqual<Rhs = Self> {
444    /// The type representing either `True` or `False`
445    type Output: Bit;
446    /// Method returning `True` or `False`.
447    #[allow(clippy::wrong_self_convention)]
448    fn is_less_or_equal(self, rhs: Rhs) -> Self::Output;
449}
450
451use crate::private::IsLessOrEqualPrivate;
452impl<A, B> IsLessOrEqual<B> for A
453where
454    A: Cmp<B> + IsLessOrEqualPrivate<B, Compare<A, B>>,
455{
456    type Output = <A as IsLessOrEqualPrivate<B, Compare<A, B>>>::Output;
457
458    #[inline]
459    fn is_less_or_equal(self, rhs: B) -> Self::Output {
460        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
461        self.is_less_or_equal_private(rhs, lhs_cmp_rhs)
462    }
463}
464
465/// A **type operator** that returns `True` if `Self != Rhs`, otherwise returns `False`.
466pub trait IsNotEqual<Rhs = Self> {
467    /// The type representing either `True` or `False`
468    type Output: Bit;
469    /// Method returning `True` or `False`.
470    #[allow(clippy::wrong_self_convention)]
471    fn is_not_equal(self, rhs: Rhs) -> Self::Output;
472}
473
474use crate::private::IsNotEqualPrivate;
475impl<A, B> IsNotEqual<B> for A
476where
477    A: Cmp<B> + IsNotEqualPrivate<B, Compare<A, B>>,
478{
479    type Output = <A as IsNotEqualPrivate<B, Compare<A, B>>>::Output;
480
481    #[inline]
482    fn is_not_equal(self, rhs: B) -> Self::Output {
483        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
484        self.is_not_equal_private(rhs, lhs_cmp_rhs)
485    }
486}
487
488/// A **type operator** that returns `True` if `Self >= Rhs`, otherwise returns `False`.
489pub trait IsGreaterOrEqual<Rhs = Self> {
490    /// The type representing either `True` or `False`
491    type Output: Bit;
492    /// Method returning `True` or `False`.
493    #[allow(clippy::wrong_self_convention)]
494    fn is_greater_or_equal(self, rhs: Rhs) -> Self::Output;
495}
496
497use crate::private::IsGreaterOrEqualPrivate;
498impl<A, B> IsGreaterOrEqual<B> for A
499where
500    A: Cmp<B> + IsGreaterOrEqualPrivate<B, Compare<A, B>>,
501{
502    type Output = <A as IsGreaterOrEqualPrivate<B, Compare<A, B>>>::Output;
503
504    #[inline]
505    fn is_greater_or_equal(self, rhs: B) -> Self::Output {
506        let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
507        self.is_greater_or_equal_private(rhs, lhs_cmp_rhs)
508    }
509}
510
511/**
512A convenience macro for comparing type numbers. Use `op!` instead.
513
514Due to the intricacies of the macro system, if the left-hand operand is more complex than a simple
515`ident`, you must place a comma between it and the comparison sign.
516
517For example, you can do `cmp!(P5 > P3)` or `cmp!(typenum::P5, > typenum::P3)` but not
518`cmp!(typenum::P5 > typenum::P3)`.
519
520The result of this comparison will always be one of `True` (aka `B1`) or `False` (aka `B0`).
521
522# Example
523```rust
524#[macro_use] extern crate typenum;
525use typenum::consts::*;
526use typenum::Bit;
527
528fn main() {
529type Result = cmp!(P9 == op!(P1 + P2 * (P2 - N2)));
530assert_eq!(Result::to_bool(), true);
531}
532```
533 */
534#[deprecated(since = "1.9.0", note = "use the `op!` macro instead")]
535#[macro_export]
536macro_rules! cmp {
537    ($a:ident < $b:ty) => {
538        <$a as $crate::IsLess<$b>>::Output
539    };
540    ($a:ty, < $b:ty) => {
541        <$a as $crate::IsLess<$b>>::Output
542    };
543
544    ($a:ident == $b:ty) => {
545        <$a as $crate::IsEqual<$b>>::Output
546    };
547    ($a:ty, == $b:ty) => {
548        <$a as $crate::IsEqual<$b>>::Output
549    };
550
551    ($a:ident > $b:ty) => {
552        <$a as $crate::IsGreater<$b>>::Output
553    };
554    ($a:ty, > $b:ty) => {
555        <$a as $crate::IsGreater<$b>>::Output
556    };
557
558    ($a:ident <= $b:ty) => {
559        <$a as $crate::IsLessOrEqual<$b>>::Output
560    };
561    ($a:ty, <= $b:ty) => {
562        <$a as $crate::IsLessOrEqual<$b>>::Output
563    };
564
565    ($a:ident != $b:ty) => {
566        <$a as $crate::IsNotEqual<$b>>::Output
567    };
568    ($a:ty, != $b:ty) => {
569        <$a as $crate::IsNotEqual<$b>>::Output
570    };
571
572    ($a:ident >= $b:ty) => {
573        <$a as $crate::IsGreaterOrEqual<$b>>::Output
574    };
575    ($a:ty, >= $b:ty) => {
576        <$a as $crate::IsGreaterOrEqual<$b>>::Output
577    };
578}
579
580/// A **type operator** for taking the integer square root of `Self`.
581///
582/// The integer square root of `n` is the largest integer `m` such
583/// that `n >= m*m`. This definition is equivalent to truncating the
584/// real-valued square root: `floor(real_sqrt(n))`.
585pub trait SquareRoot {
586    /// The result of the integer square root.
587    type Output;
588}
589
590/// A **type operator** for taking the integer binary logarithm of `Self`.
591///
592/// The integer binary logarighm of `n` is the largest integer `m` such
593/// that `n >= 2^m`. This definition is equivalent to truncating the
594/// real-valued binary logarithm: `floor(log2(n))`.
595pub trait Logarithm2 {
596    /// The result of the integer binary logarithm.
597    type Output;
598}
599
600/// A **type operator** that computes the [greatest common divisor][gcd] of `Self` and `Rhs`.
601///
602/// [gcd]: https://en.wikipedia.org/wiki/Greatest_common_divisor
603///
604/// # Example
605///
606/// ```rust
607/// use typenum::{Gcd, Unsigned, U12, U8};
608///
609/// assert_eq!(<U12 as Gcd<U8>>::Output::to_i32(), 4);
610/// ```
611pub trait Gcd<Rhs> {
612    /// The greatest common divisor.
613    type Output;
614}
615
616/// A **type operator** for taking a concrete integer value from a type.
617///
618/// It returns arbitrary integer value without explicitly specifying the
619/// type. It is useful when you pass the values to methods that accept
620/// distinct types without runtime casting.
621pub trait ToInt<T> {
622    /// Method returning the concrete value for the type.
623    fn to_int() -> T;
624    /// The concrete value for the type. Can be used in `const` contexts.
625    const INT: T;
626}
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy