palette/
num.rs

1//! Traits for abstracting over numeric types.
2//!
3//! These traits describe various numeric properties and operations. They are
4//! similar in purpose to the immensely helpful traits in
5//! [`num-traits`](https://crates.io/crates/num-traits/), but the structure is
6//! different. The philosophy behind this module is to focus on capabilities,
7//! rather than categories, and to assume as little as possible. Within reason.
8//!
9//! Instead of having large traits with a lot of methods and dependencies, each
10//! operation (or group of operations), are separated into their own traits.
11//! This allows number types to have partial compatibility by only implementing
12//! some of the traits, and new methods can be added as new traits without
13//! affecting old functionality.
14
15use core::ops::{Add, Div, Mul, Neg, Sub};
16
17use crate::bool_mask::HasBoolMask;
18
19#[cfg(all(not(feature = "std"), feature = "libm"))]
20mod libm;
21#[cfg(feature = "wide")]
22mod wide;
23
24/// Numbers that belong to the real number set. It's both a semantic marker and
25/// provides a constructor for number constants.
26pub trait Real {
27    /// Create a number from an `f64` value, mainly for converting constants.
28    #[must_use]
29    fn from_f64(n: f64) -> Self;
30}
31
32/// Trait for creating a vectorized value from a scalar value.
33pub trait FromScalar {
34    /// The scalar type that is stored in each lane of `Self`. Scalar types
35    /// should set this to equal `Self`.
36    type Scalar;
37
38    /// Create a new vectorized value where each lane is `scalar`. This
39    /// corresponds to `splat` for SIMD types.
40    #[must_use]
41    fn from_scalar(scalar: Self::Scalar) -> Self;
42}
43
44/// Conversion from an array of scalars to a vectorized value.
45pub trait FromScalarArray<const N: usize>: FromScalar {
46    /// Creates a vectorized value from an array of scalars.
47    #[must_use]
48    fn from_array(scalars: [Self::Scalar; N]) -> Self;
49}
50
51/// Conversion from a vectorized value to an array of scalars.
52pub trait IntoScalarArray<const N: usize>: FromScalar {
53    /// Creates an array of scalars from a vectorized value.
54    #[must_use]
55    fn into_array(self) -> [Self::Scalar; N];
56}
57
58/// Methods for the value `0`.
59pub trait Zero {
60    /// Create a new `0` value.
61    #[must_use]
62    fn zero() -> Self;
63}
64
65/// Methods for the value `1`.
66pub trait One {
67    /// Create a new `1` value.
68    #[must_use]
69    fn one() -> Self;
70}
71
72/// A helper trait that collects arithmetic traits under one name.
73pub trait Arithmetics
74where
75    Self: Add<Output = Self>
76        + Sub<Output = Self>
77        + Mul<Output = Self>
78        + Div<Output = Self>
79        + Neg<Output = Self>
80        + Sized,
81    for<'a> Self: Add<&'a Self, Output = Self>
82        + Sub<&'a Self, Output = Self>
83        + Mul<&'a Self, Output = Self>
84        + Div<&'a Self, Output = Self>,
85{
86}
87
88impl<T> Arithmetics for T
89where
90    T: Add<Output = Self>
91        + Sub<Output = Self>
92        + Mul<Output = Self>
93        + Div<Output = Self>
94        + Neg<Output = Self>
95        + Sized,
96    for<'a> Self: Add<&'a Self, Output = Self>
97        + Sub<&'a Self, Output = Self>
98        + Mul<&'a Self, Output = Self>
99        + Div<&'a Self, Output = Self>,
100{
101}
102
103/// Methods for getting the largest or smallest of two values.
104pub trait MinMax: Sized {
105    /// Return the smallest of `self` and `other`.
106    #[must_use]
107    fn min(self, other: Self) -> Self;
108
109    /// Return the largest of `self` and `other`.
110    #[must_use]
111    fn max(self, other: Self) -> Self;
112
113    /// Return a pair of `self` and `other`, where the smallest is the first
114    /// value and the largest is the second.
115    #[must_use]
116    fn min_max(self, other: Self) -> (Self, Self);
117}
118
119/// Trigonometry methods and their inverses.
120pub trait Trigonometry: Sized {
121    /// Compute the sine of `self` (in radians).
122    #[must_use]
123    fn sin(self) -> Self;
124
125    /// Compute the cosine of `self` (in radians).
126    #[must_use]
127    fn cos(self) -> Self;
128
129    /// Simultaneously compute the sine and cosine of `self` (in radians).
130    /// Returns `(sin(self), cos(self))`.
131    #[must_use]
132    fn sin_cos(self) -> (Self, Self);
133
134    /// Compute the tangent of `self` (in radians).
135    #[must_use]
136    fn tan(self) -> Self;
137
138    /// Compute the arcsine in radians of `self`.
139    #[must_use]
140    fn asin(self) -> Self;
141
142    /// Compute the arccosine in radians of `self`.
143    #[must_use]
144    fn acos(self) -> Self;
145
146    /// Compute the arctangent in radians of `self`.
147    #[must_use]
148    fn atan(self) -> Self;
149
150    /// Compute the arctangent in radians of `self` (y) and `other` (x).
151    #[must_use]
152    fn atan2(self, other: Self) -> Self;
153}
154
155/// Method for getting the absolute value of a number.
156pub trait Abs {
157    /// Returns the absolute value of `self`.
158    #[must_use]
159    fn abs(self) -> Self;
160}
161
162/// Method for getting the square root of a number.
163pub trait Sqrt {
164    /// Returns the square root of `self`.
165    #[must_use]
166    fn sqrt(self) -> Self;
167}
168
169/// Method for getting the cube root of a number.
170pub trait Cbrt {
171    /// Returns the cube root of `self`.
172    #[must_use]
173    fn cbrt(self) -> Self;
174}
175
176/// Method for raising a number by a real number exponent.
177///
178/// The name "powf" is kept for familiarity, even though the exponent doesn't
179/// have to be a floating point number.
180pub trait Powf {
181    /// Return `self` raised to the power of `exp`.
182    #[must_use]
183    fn powf(self, exp: Self) -> Self;
184}
185
186/// Method for raising a number by a signed integer exponent.
187pub trait Powi {
188    /// Return `self` raised to the power of `exp`.
189    #[must_use]
190    fn powi(self, exp: i32) -> Self;
191}
192
193/// Method for raising a number by a n unsigned integer exponent.
194pub trait Powu {
195    /// Return `self` raised to the power of `exp`.
196    #[must_use]
197    fn powu(self, exp: u32) -> Self;
198}
199
200/// Method for calculating `1 / x`.
201pub trait Recip {
202    /// Return `1 / self`.
203    #[must_use]
204    fn recip(self) -> Self;
205}
206
207/// Methods for calculating `e ^ x`,
208pub trait Exp {
209    /// Return `e ^ self`.
210    #[must_use]
211    fn exp(self) -> Self;
212}
213
214/// Methods for checking if a number can be used as a divisor.
215pub trait IsValidDivisor: HasBoolMask {
216    /// Return `true` if `self` can be used as a divisor in `x / self`.
217    ///
218    /// This checks that division by `self` will result in a finite and defined
219    /// value. Integers check for `self != 0`, while floating point types call
220    /// [`is_normal`][std::primitive::f32::is_normal].
221    #[must_use]
222    fn is_valid_divisor(&self) -> Self::Mask;
223}
224
225/// Methods for calculating the lengths of a hypotenuse.
226pub trait Hypot {
227    /// Returns the length of the hypotenuse formed by `self` and `other`, i.e.
228    /// `sqrt(self * self + other * other)`.
229    #[must_use]
230    fn hypot(self, other: Self) -> Self;
231}
232
233/// Methods for rounding numbers to integers.
234pub trait Round {
235    /// Return the nearest integer to `self`. Round half-way cases away from 0.0.
236    #[must_use]
237    fn round(self) -> Self;
238
239    /// Return the largest integer less than or equal to `self`.
240    #[must_use]
241    fn floor(self) -> Self;
242
243    /// Return the smallest integer greater than or equal to `self`.
244    #[must_use]
245    fn ceil(self) -> Self;
246}
247
248/// Trait for clamping a value.
249pub trait Clamp {
250    /// Clamp self to be within the range `[min, max]`.
251    #[must_use]
252    fn clamp(self, min: Self, max: Self) -> Self;
253
254    /// Clamp self to be within the range `[min, ∞)`.
255    #[must_use]
256    fn clamp_min(self, min: Self) -> Self;
257
258    /// Clamp self to be within the range `(-∞, max]`.
259    #[must_use]
260    fn clamp_max(self, max: Self) -> Self;
261}
262
263/// Assigning trait for clamping a value.
264pub trait ClampAssign {
265    /// Clamp self to be within the range `[min, max]`.
266    fn clamp_assign(&mut self, min: Self, max: Self);
267
268    /// Clamp self to be within the range `[min, ∞)`.
269    fn clamp_min_assign(&mut self, min: Self);
270
271    /// Clamp self to be within the range `(-∞, max]`.
272    fn clamp_max_assign(&mut self, max: Self);
273}
274
275/// Combined multiplication and addition operation.
276pub trait MulAdd {
277    /// Multiplies self with `m` and add `a`, as in `(self * m) + a`.
278    #[must_use]
279    fn mul_add(self, m: Self, a: Self) -> Self;
280}
281
282/// Combined multiplication and subtraction operation.
283pub trait MulSub {
284    /// Multiplies self with `m` and subtract `s`, as in `(self * m) - s`.
285    #[must_use]
286    fn mul_sub(self, m: Self, s: Self) -> Self;
287}
288
289/// Saturating addition operation.
290pub trait SaturatingAdd<Rhs = Self> {
291    /// The resulting type.
292    type Output;
293
294    /// Returns the sum of `self` and `other`, but saturates instead of overflowing.
295    #[must_use]
296    fn saturating_add(self, other: Rhs) -> Self::Output;
297}
298
299/// Saturating subtraction operation.
300pub trait SaturatingSub<Rhs = Self> {
301    /// The resulting type.
302    type Output;
303
304    /// Returns the difference of `self` and `other`, but saturates instead of overflowing.
305    #[must_use]
306    fn saturating_sub(self, other: Rhs) -> Self::Output;
307}
308
309/// Trait for getting a number that represents the sign of `self`.
310pub trait Signum {
311    /// Returns a number that represents the sign of `self`. For floating point:
312    ///
313    /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
314    /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
315    /// * NaN if the number is NaN
316    fn signum(self) -> Self;
317}
318
319/// Trait for getting the natural logarithm of `self`.
320pub trait Ln {
321    /// Returns the natural logarithm of `self`.
322    fn ln(self) -> Self;
323}
324
325macro_rules! impl_uint {
326    ($($ty: ident),+) => {
327        $(
328            impl FromScalar for $ty {
329                type Scalar = Self;
330
331                #[inline]
332                fn from_scalar(scalar: Self) -> Self {
333                    scalar
334                }
335            }
336
337            impl FromScalarArray<1> for $ty {
338                #[inline]
339                fn from_array(scalars: [Self; 1]) -> Self {
340                    let [scalar] = scalars;
341                    scalar
342                }
343            }
344
345            impl IntoScalarArray<1> for $ty {
346                #[inline]
347                fn into_array(self) -> [Self; 1] {
348                    [self]
349                }
350            }
351
352            impl Zero for $ty {
353                #[inline]
354                fn zero() -> Self {
355                    0
356                }
357            }
358
359            impl One for $ty {
360                #[inline]
361                fn one() -> Self {
362                    1
363                }
364            }
365
366            impl MinMax for $ty {
367                #[inline]
368                fn min(self, other: Self) -> Self {
369                    core::cmp::Ord::min(self, other)
370                }
371
372                #[inline]
373                fn max(self, other: Self) -> Self {
374                    core::cmp::Ord::max(self, other)
375                }
376
377                #[inline]
378                fn min_max(self, other: Self) -> (Self, Self) {
379                    if self > other {
380                        (other, self)
381                    } else {
382                        (self, other)
383                    }
384                }
385            }
386
387            impl Powu for $ty {
388                #[inline]
389                fn powu(self, exp: u32) -> Self {
390                    pow(self, exp)
391                }
392            }
393
394            impl IsValidDivisor for $ty {
395                #[inline]
396                fn is_valid_divisor(&self) -> bool {
397                    *self != 0
398                }
399            }
400
401            impl Clamp for $ty {
402                #[inline]
403                fn clamp(self, min: Self, max: Self) -> Self {
404                    core::cmp::Ord::clamp(self, min, max)
405                }
406
407                #[inline]
408                fn clamp_min(self, min: Self) -> Self {
409                    core::cmp::Ord::max(self, min)
410                }
411
412                #[inline]
413                fn clamp_max(self, max: Self) -> Self {
414                    core::cmp::Ord::min(self, max)
415                }
416            }
417
418            impl ClampAssign for $ty {
419                #[inline]
420                fn clamp_assign(&mut self, min: Self, max: Self) {
421                    *self = core::cmp::Ord::clamp(*self, min, max);
422                }
423
424                #[inline]
425                fn clamp_min_assign(&mut self, min: Self) {
426                    *self = core::cmp::Ord::max(*self, min);
427                }
428
429                #[inline]
430                fn clamp_max_assign(&mut self, max: Self) {
431                    *self = core::cmp::Ord::min(*self, max);
432                }
433            }
434
435            impl MulAdd for $ty {
436                #[inline]
437                fn mul_add(self, m: Self, a: Self) -> Self {
438                    (self * m) + a
439                }
440            }
441
442            impl MulSub for $ty {
443                #[inline]
444                fn mul_sub(self, m: Self, s: Self) -> Self {
445                    (self * m) - s
446                }
447            }
448
449            impl SaturatingAdd for $ty {
450                type Output = $ty;
451                #[inline]
452                fn saturating_add(self, other: Self) -> Self{
453                    <$ty>::saturating_add(self, other)
454                }
455            }
456
457            impl SaturatingSub for $ty {
458                type Output = $ty;
459                #[inline]
460                fn saturating_sub(self, other: Self) -> Self{
461                    <$ty>::saturating_sub(self, other)
462                }
463            }
464        )+
465    };
466}
467
468macro_rules! impl_float {
469    ($($ty: ident),+) => {
470        $(
471            impl Real for $ty {
472                #[inline]
473                fn from_f64(n: f64) -> $ty {
474                    n as $ty
475                }
476            }
477
478            impl FromScalar for $ty {
479                type Scalar = Self;
480
481                #[inline]
482                fn from_scalar(scalar: Self) -> Self {
483                    scalar
484                }
485            }
486
487            impl FromScalarArray<1> for $ty {
488                #[inline]
489                fn from_array(scalars: [Self; 1]) -> Self {
490                    let [scalar] = scalars;
491                    scalar
492                }
493            }
494
495            impl IntoScalarArray<1> for $ty {
496                #[inline]
497                fn into_array(self) -> [Self; 1] {
498                    [self]
499                }
500            }
501
502            impl Zero for $ty {
503                #[inline]
504                fn zero() -> Self {
505                    0.0
506                }
507            }
508
509            impl One for $ty {
510                #[inline]
511                fn one() -> Self {
512                    1.0
513                }
514            }
515
516            impl MinMax for $ty {
517                #[inline]
518                fn max(self, other: Self) -> Self {
519                    $ty::max(self, other)
520                }
521
522                #[inline]
523                fn min(self, other: Self) -> Self {
524                    $ty::min(self, other)
525                }
526
527                #[inline]
528                fn min_max(self, other: Self) -> (Self, Self) {
529                    if self > other {
530                        (other, self)
531                    } else {
532                        (self, other)
533                    }
534                }
535            }
536
537            impl Powu for $ty {
538                #[inline]
539                fn powu(self, exp: u32) -> Self {
540                    pow(self, exp)
541                }
542            }
543
544            impl IsValidDivisor for $ty {
545                #[inline]
546                fn is_valid_divisor(&self) -> bool {
547                    $ty::is_normal(*self)
548                }
549            }
550
551            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
552            impl Trigonometry for $ty {
553                #[inline]
554                fn sin(self) -> Self {
555                    $ty::sin(self)
556                }
557
558                #[inline]
559                fn cos(self) -> Self {
560                    $ty::cos(self)
561                }
562
563                #[inline]
564                fn sin_cos(self) -> (Self, Self) {
565                    $ty::sin_cos(self)
566                }
567
568                #[inline]
569                fn tan(self) -> Self {
570                    $ty::tan(self)
571                }
572
573                #[inline]
574                fn asin(self) -> Self {
575                    $ty::asin(self)
576                }
577
578                #[inline]
579                fn acos(self) -> Self {
580                    $ty::acos(self)
581                }
582
583                #[inline]
584                fn atan(self) -> Self {
585                    $ty::atan(self)
586                }
587
588                #[inline]
589                fn atan2(self, other: Self) -> Self {
590                    $ty::atan2(self, other)
591                }
592            }
593
594            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
595            impl Abs for $ty {
596                #[inline]
597                fn abs(self) -> Self {
598                    $ty::abs(self)
599                }
600            }
601
602            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
603            impl Sqrt for $ty {
604                #[inline]
605                fn sqrt(self) -> Self {
606                    $ty::sqrt(self)
607                }
608            }
609
610            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
611            impl Cbrt for $ty {
612                #[inline]
613                fn cbrt(self) -> Self {
614                    $ty::cbrt(self)
615                }
616            }
617
618            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
619            impl Powf for $ty {
620                #[inline]
621                fn powf(self, exp: Self) -> Self {
622                    $ty::powf(self, exp)
623                }
624            }
625
626            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
627            impl Powi for $ty {
628                #[inline]
629                fn powi(self, exp: i32) -> Self {
630                    $ty::powi(self, exp)
631                }
632            }
633
634            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
635            impl Recip for $ty {
636                #[inline]
637                fn recip(self) -> Self {
638                    $ty::recip(self)
639                }
640            }
641
642            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
643            impl Exp for $ty {
644                #[inline]
645                fn exp(self) -> Self {
646                    $ty::exp(self)
647                }
648            }
649
650            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
651            impl Hypot for $ty {
652                #[inline]
653                fn hypot(self, other: Self) -> Self {
654                    $ty::hypot(self, other)
655                }
656            }
657
658            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
659            impl Round for $ty {
660                #[inline]
661                fn round(self) -> Self {
662                    $ty::round(self)
663                }
664
665                #[inline]
666                fn floor(self) -> Self {
667                    $ty::floor(self)
668                }
669
670                #[inline]
671                fn ceil(self) -> Self {
672                    $ty::ceil(self)
673                }
674            }
675
676            impl Clamp for $ty {
677                #[inline]
678                fn clamp(self, min: Self, max: Self) -> Self {
679                    $ty::clamp(self, min, max)
680                }
681
682                #[inline]
683                fn clamp_min(self, min: Self) -> Self {
684                    $ty::max(self, min)
685                }
686
687                #[inline]
688                fn clamp_max(self, max: Self) -> Self {
689                    $ty::min(self, max)
690                }
691            }
692
693            impl ClampAssign for $ty {
694                #[inline]
695                fn clamp_assign(&mut self, min: Self, max: Self) {
696                    *self = $ty::clamp(*self, min, max);
697                }
698
699                #[inline]
700                fn clamp_min_assign(&mut self, min: Self) {
701                    *self = $ty::max(*self, min);
702                }
703
704                #[inline]
705                fn clamp_max_assign(&mut self, max: Self) {
706                    *self = $ty::min(*self, max);
707                }
708            }
709
710            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
711            impl MulAdd for $ty {
712                #[inline]
713                fn mul_add(self, m: Self, a: Self) -> Self {
714                    $ty::mul_add(self, m, a)
715                }
716            }
717
718            impl MulSub for $ty {
719                #[inline]
720                fn mul_sub(self, m: Self, s: Self) -> Self {
721                    (self * m) - s
722                }
723            }
724
725            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
726            impl Signum for $ty {
727                #[inline]
728                fn signum(self) -> Self {
729                    $ty::signum(self)
730                }
731            }
732
733            #[cfg(any(feature = "std", all(test, not(feature = "libm"))))]
734            impl Ln for $ty {
735                #[inline]
736                fn ln(self) -> Self {
737                    $ty::ln(self)
738                }
739            }
740        )+
741    };
742}
743
744impl_uint!(u8, u16, u32, u64, u128);
745impl_float!(f32, f64);
746
747/// "borrowed" from num_traits
748///
749/// Raises a value to the power of exp, using exponentiation by squaring.
750///
751/// Note that `0⁰` (`pow(0, 0)`) returns `1`. Mathematically this is undefined.
752//
753// # Example
754//
755// ```rust
756// use num_traits::pow;
757//
758// assert_eq!(pow(2i8, 4), 16);
759// assert_eq!(pow(6u8, 3), 216);
760// assert_eq!(pow(0u8, 0), 1); // Be aware if this case affects you
761// ```
762#[inline]
763fn pow<T: Clone + One + Mul<T, Output = T>>(mut base: T, mut exp: u32) -> T {
764    if exp == 0 {
765        return T::one();
766    }
767
768    while exp & 1 == 0 {
769        base = base.clone() * base;
770        exp >>= 1;
771    }
772    if exp == 1 {
773        return base;
774    }
775
776    let mut acc = base.clone();
777    while exp > 1 {
778        exp >>= 1;
779        base = base.clone() * base;
780        if exp & 1 == 1 {
781            acc = acc * base.clone();
782        }
783    }
784    acc
785}
786
787/// Trait for lanewise comparison of two values.
788///
789/// This is similar to `PartialEq` and `PartialOrd`, except that it returns a
790/// Boolean mask instead of `bool` or [`Ordering`][core::cmp::Ordering].
791pub trait PartialCmp: HasBoolMask {
792    /// Compares `self < other`.
793    #[must_use]
794    fn lt(&self, other: &Self) -> Self::Mask;
795
796    /// Compares `self <= other`.
797    #[must_use]
798    fn lt_eq(&self, other: &Self) -> Self::Mask;
799
800    /// Compares `self == other`.
801    #[must_use]
802    fn eq(&self, other: &Self) -> Self::Mask;
803
804    /// Compares `self != other`.
805    #[must_use]
806    fn neq(&self, other: &Self) -> Self::Mask;
807
808    /// Compares `self >= other`.
809    #[must_use]
810    fn gt_eq(&self, other: &Self) -> Self::Mask;
811
812    /// Compares `self > other`.
813    #[must_use]
814    fn gt(&self, other: &Self) -> Self::Mask;
815}
816
817macro_rules! impl_partial_cmp {
818    ($($ty:ident),+) => {
819        $(
820            impl PartialCmp for $ty {
821                #[inline]
822                fn lt(&self, other: &Self) -> Self::Mask {
823                    self < other
824                }
825
826                #[inline]
827                fn lt_eq(&self, other: &Self) -> Self::Mask {
828                    self <= other
829                }
830
831                #[inline]
832                fn eq(&self, other: &Self) -> Self::Mask {
833                    self == other
834                }
835
836                #[inline]
837                fn neq(&self, other: &Self) -> Self::Mask {
838                    self != other
839                }
840
841                #[inline]
842                fn gt_eq(&self, other: &Self) -> Self::Mask {
843                    self >= other
844                }
845
846                #[inline]
847                fn gt(&self, other: &Self) -> Self::Mask {
848                    self > other
849                }
850            }
851        )+
852    };
853}
854
855impl_partial_cmp!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);