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: >::Output = 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: >::Output = 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: >::Output = 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: >::Output = 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: >::Output = 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: >::Output = 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}
627