1use crate::{
4 private::{Internal, InternalMarker},
5 Bit, NInt, NonZero, PInt, UInt, UTerm, Unsigned, Z0,
6};
7
8pub trait Same<Rhs = Self> {
30 type Output;
32}
33
34impl<T> Same<T> for T {
35 type Output = T;
36}
37
38pub trait Abs {
47 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
63pub trait Pow<Exp> {
72 type Output;
74 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 #[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 #[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 ($t: ty $(, $tail:tt)*) => (
193 impl Pow<UTerm> for $t {
194 type Output = $t;
195 #[inline]
196 fn powi(self, _: UTerm) -> Self::Output {
197 1
198 }
199 }
200
201 impl<U: Unsigned, B: Bit> Pow<UInt<U, B>> for $t {
202 type Output = $t;
203 #[inline]
204 fn powi(self, _: UInt<U, B>) -> Self::Output {
205 self.pow(<UInt<U, B> as Unsigned>::to_u32())
206 }
207 }
208
209 impl Pow<Z0> for $t {
210 type Output = $t;
211 #[inline]
212 fn powi(self, _: Z0) -> Self::Output {
213 1
214 }
215 }
216
217 impl<U: Unsigned + NonZero> Pow<PInt<U>> for $t {
218 type Output = $t;
219 #[inline]
220 fn powi(self, _: PInt<U>) -> Self::Output {
221 self.pow(U::to_u32())
222 }
223 }
224
225 impl_pow_i!($($tail),*);
226 );
227}
228
229impl_pow_i!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
230#[cfg(feature = "i128")]
231impl_pow_i!(u128, i128);
232
233#[test]
234fn pow_test() {
235 use crate::consts::*;
236 let z0 = Z0::new();
237 let p3 = P3::new();
238
239 let u0 = U0::new();
240 let u3 = U3::new();
241 let n3 = N3::new();
242
243 macro_rules! check {
244 ($x:ident) => {
245 assert_eq!($x.powi(z0), 1);
246 assert_eq!($x.powi(u0), 1);
247
248 assert_eq!($x.powi(p3), $x * $x * $x);
249 assert_eq!($x.powi(u3), $x * $x * $x);
250 };
251 ($x:ident, $f:ident) => {
252 assert!((<$f as Pow<Z0>>::powi(*$x, z0) - 1.0).abs() < ::core::$f::EPSILON);
253 assert!((<$f as Pow<U0>>::powi(*$x, u0) - 1.0).abs() < ::core::$f::EPSILON);
254
255 assert!((<$f as Pow<P3>>::powi(*$x, p3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
256 assert!((<$f as Pow<U3>>::powi(*$x, u3) - $x * $x * $x).abs() < ::core::$f::EPSILON);
257
258 if *$x == 0.0 {
259 assert!(<$f as Pow<N3>>::powi(*$x, n3).is_infinite());
260 } else {
261 assert!(
262 (<$f as Pow<N3>>::powi(*$x, n3) - 1. / $x / $x / $x).abs()
263 < ::core::$f::EPSILON
264 );
265 }
266 };
267 }
268
269 for x in &[0i8, -3, 2] {
270 check!(x);
271 }
272 for x in &[0u8, 1, 5] {
273 check!(x);
274 }
275 for x in &[0usize, 1, 5, 40] {
276 check!(x);
277 }
278 for x in &[0isize, 1, 2, -30, -22, 48] {
279 check!(x);
280 }
281 for x in &[0.0f32, 2.2, -3.5, 378.223] {
282 check!(x, f32);
283 }
284 for x in &[0.0f64, 2.2, -3.5, -2387.2, 234.22] {
285 check!(x, f64);
286 }
287}
288
289pub trait Cmp<Rhs = Self> {
303 type Output;
305
306 #[doc(hidden)]
307 fn compare<IM: InternalMarker>(&self, _: &Rhs) -> Self::Output;
308}
309
310pub trait Len {
312 type Output: crate::Unsigned;
314 fn len(&self) -> Self::Output;
316}
317
318pub trait PartialDiv<Rhs = Self> {
321 type Output;
323 fn partial_div(self, _: Rhs) -> Self::Output;
325}
326
327pub trait Min<Rhs = Self> {
329 type Output;
331 fn min(self, rhs: Rhs) -> Self::Output;
333}
334
335pub trait Max<Rhs = Self> {
337 type Output;
339 fn max(self, rhs: Rhs) -> Self::Output;
341}
342
343use crate::Compare;
344
345pub trait IsLess<Rhs = Self> {
347 type Output: Bit;
349 fn is_less(self, rhs: Rhs) -> Self::Output;
351}
352
353use crate::private::IsLessPrivate;
354impl<A, B> IsLess<B> for A
355where
356 A: Cmp<B> + IsLessPrivate<B, Compare<A, B>>,
357{
358 type Output = <A as IsLessPrivate<B, Compare<A, B>>>::Output;
359
360 #[inline]
361 fn is_less(self, rhs: B) -> Self::Output {
362 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
363 self.is_less_private(rhs, lhs_cmp_rhs)
364 }
365}
366
367pub trait IsEqual<Rhs = Self> {
369 type Output: Bit;
371 fn is_equal(self, rhs: Rhs) -> Self::Output;
373}
374
375use crate::private::IsEqualPrivate;
376impl<A, B> IsEqual<B> for A
377where
378 A: Cmp<B> + IsEqualPrivate<B, Compare<A, B>>,
379{
380 type Output = <A as IsEqualPrivate<B, Compare<A, B>>>::Output;
381
382 #[inline]
383 fn is_equal(self, rhs: B) -> Self::Output {
384 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
385 self.is_equal_private(rhs, lhs_cmp_rhs)
386 }
387}
388
389pub trait IsGreater<Rhs = Self> {
391 type Output: Bit;
393 fn is_greater(self, rhs: Rhs) -> Self::Output;
395}
396
397use crate::private::IsGreaterPrivate;
398impl<A, B> IsGreater<B> for A
399where
400 A: Cmp<B> + IsGreaterPrivate<B, Compare<A, B>>,
401{
402 type Output = <A as IsGreaterPrivate<B, Compare<A, B>>>::Output;
403
404 #[inline]
405 fn is_greater(self, rhs: B) -> Self::Output {
406 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
407 self.is_greater_private(rhs, lhs_cmp_rhs)
408 }
409}
410
411pub trait IsLessOrEqual<Rhs = Self> {
413 type Output: Bit;
415 fn is_less_or_equal(self, rhs: Rhs) -> Self::Output;
417}
418
419use crate::private::IsLessOrEqualPrivate;
420impl<A, B> IsLessOrEqual<B> for A
421where
422 A: Cmp<B> + IsLessOrEqualPrivate<B, Compare<A, B>>,
423{
424 type Output = <A as IsLessOrEqualPrivate<B, Compare<A, B>>>::Output;
425
426 #[inline]
427 fn is_less_or_equal(self, rhs: B) -> Self::Output {
428 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
429 self.is_less_or_equal_private(rhs, lhs_cmp_rhs)
430 }
431}
432
433pub trait IsNotEqual<Rhs = Self> {
435 type Output: Bit;
437 fn is_not_equal(self, rhs: Rhs) -> Self::Output;
439}
440
441use crate::private::IsNotEqualPrivate;
442impl<A, B> IsNotEqual<B> for A
443where
444 A: Cmp<B> + IsNotEqualPrivate<B, Compare<A, B>>,
445{
446 type Output = <A as IsNotEqualPrivate<B, Compare<A, B>>>::Output;
447
448 #[inline]
449 fn is_not_equal(self, rhs: B) -> Self::Output {
450 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
451 self.is_not_equal_private(rhs, lhs_cmp_rhs)
452 }
453}
454
455pub trait IsGreaterOrEqual<Rhs = Self> {
457 type Output: Bit;
459 fn is_greater_or_equal(self, rhs: Rhs) -> Self::Output;
461}
462
463use crate::private::IsGreaterOrEqualPrivate;
464impl<A, B> IsGreaterOrEqual<B> for A
465where
466 A: Cmp<B> + IsGreaterOrEqualPrivate<B, Compare<A, B>>,
467{
468 type Output = <A as IsGreaterOrEqualPrivate<B, Compare<A, B>>>::Output;
469
470 #[inline]
471 fn is_greater_or_equal(self, rhs: B) -> Self::Output {
472 let lhs_cmp_rhs = self.compare::<Internal>(&rhs);
473 self.is_greater_or_equal_private(rhs, lhs_cmp_rhs)
474 }
475}
476
477#[deprecated(since = "1.9.0", note = "use the `op!` macro instead")]
501#[macro_export]
502macro_rules! cmp {
503 ($a:ident < $b:ty) => {
504 <$a as $crate::IsLess<$b>>::Output
505 };
506 ($a:ty, < $b:ty) => {
507 <$a as $crate::IsLess<$b>>::Output
508 };
509
510 ($a:ident == $b:ty) => {
511 <$a as $crate::IsEqual<$b>>::Output
512 };
513 ($a:ty, == $b:ty) => {
514 <$a as $crate::IsEqual<$b>>::Output
515 };
516
517 ($a:ident > $b:ty) => {
518 <$a as $crate::IsGreater<$b>>::Output
519 };
520 ($a:ty, > $b:ty) => {
521 <$a as $crate::IsGreater<$b>>::Output
522 };
523
524 ($a:ident <= $b:ty) => {
525 <$a as $crate::IsLessOrEqual<$b>>::Output
526 };
527 ($a:ty, <= $b:ty) => {
528 <$a as $crate::IsLessOrEqual<$b>>::Output
529 };
530
531 ($a:ident != $b:ty) => {
532 <$a as $crate::IsNotEqual<$b>>::Output
533 };
534 ($a:ty, != $b:ty) => {
535 <$a as $crate::IsNotEqual<$b>>::Output
536 };
537
538 ($a:ident >= $b:ty) => {
539 <$a as $crate::IsGreaterOrEqual<$b>>::Output
540 };
541 ($a:ty, >= $b:ty) => {
542 <$a as $crate::IsGreaterOrEqual<$b>>::Output
543 };
544}
545
546pub trait SquareRoot {
552 type Output;
554}
555
556pub trait Logarithm2 {
562 type Output;
564}
565
566pub trait Gcd<Rhs> {
578 type Output;
580}
581
582pub trait ToInt<T> {
588 fn to_int() -> T;
590}