Skip to main content

unit_intervals/
unit_interval.rs

1use crate::UnitIntervalFloat;
2use core::{
3    cmp::Ordering,
4    error::Error,
5    fmt,
6    ops::{Add, Deref, Div, Mul, Neg, Rem, Sub},
7};
8
9/// A floating-point value constrained to the closed unit interval `[0, 1]`.
10///
11/// `UnitInterval` is useful for normalized values such as opacity, progress,
12/// ratios, blend factors, and percentages represented as fractions.
13///
14/// The default backing type is `f32`; use `UnitInterval<f64>` when you need a
15/// wider float.
16///
17/// # Examples
18///
19/// ```
20/// use unit_intervals::UnitInterval;
21///
22/// let progress = UnitInterval::new(0.75).unwrap();
23///
24/// assert_eq!(progress.get(), 0.75);
25/// assert_eq!(UnitInterval::new(1.25), None);
26/// ```
27#[cfg_attr(
28    feature = "rkyv",
29    derive(::rkyv::Archive, ::rkyv::Serialize),
30    rkyv(crate = ::rkyv)
31)]
32#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
33#[repr(transparent)]
34pub struct UnitInterval<T = f32>(T);
35
36/// Error returned when converting an out-of-range value into a [`UnitInterval`].
37///
38/// # Examples
39///
40/// ```
41/// use unit_intervals::UnitInterval;
42///
43/// let err = UnitInterval::<f32>::try_from(2.0).unwrap_err();
44///
45/// assert_eq!(err.to_string(), "value is outside the unit interval");
46/// ```
47#[derive(Debug, Copy, Clone, Eq, PartialEq)]
48pub struct UnitIntervalError;
49
50impl fmt::Display for UnitIntervalError {
51    #[inline]
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        f.write_str("value is outside the unit interval")
54    }
55}
56
57impl Error for UnitIntervalError {}
58
59#[cfg(feature = "rkyv")]
60#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
61mod rkyv {
62    use super::*;
63    use ::rkyv::{
64        Archive, Deserialize,
65        rancor::{Fallible, Source, fail},
66    };
67
68    impl<T, D> Deserialize<UnitInterval<T>, D> for ArchivedUnitInterval<T>
69    where
70        T: Archive + UnitIntervalFloat,
71        T::Archived: Deserialize<T, D>,
72        D: Fallible + ?Sized,
73        D::Error: Source,
74    {
75        #[inline]
76        fn deserialize(&self, deserializer: &mut D) -> Result<UnitInterval<T>, D::Error> {
77            let value = self.0.deserialize(deserializer)?;
78
79            if let Some(value) = UnitInterval::new(value) {
80                Ok(value)
81            } else {
82                fail!(UnitIntervalError);
83            }
84        }
85    }
86}
87
88#[cfg(feature = "serde")]
89#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
90mod serde {
91    use super::*;
92    use ::serde::{Deserialize, Deserializer, Serialize, Serializer, de};
93
94    impl<T: Serialize> Serialize for UnitInterval<T> {
95        #[inline]
96        fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
97            self.0.serialize(serializer)
98        }
99    }
100
101    impl<'de, T> Deserialize<'de> for UnitInterval<T>
102    where
103        T: UnitIntervalFloat + Deserialize<'de>,
104    {
105        #[inline]
106        fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
107            // Keep deserialization on the same invariant-preserving path as
108            // construction from a raw float. Serialization is intentionally
109            // transparent, so the data format only stores the inner value and
110            // cannot encode whether that value came from a previously checked
111            // `UnitInterval`. Treating decoded input as trusted wrapper state
112            // would let out-of-range values and `NaN` bypass the type's public
113            // contract. Decoding the backing value first and then routing it
114            // through `new` gives every serde format the same behavior as
115            // `TryFrom<T>`: valid values reconstruct the wrapper, and invalid
116            // values become ordinary deserialization errors.
117            let value = T::deserialize(deserializer)?;
118
119            Self::new(value).ok_or_else(|| de::Error::custom(UnitIntervalError))
120        }
121    }
122}
123
124#[cfg(feature = "bytemuck")]
125#[cfg_attr(docsrs, doc(cfg(feature = "bytemuck")))]
126mod bytemuck {
127    use super::*;
128
129    unsafe impl<T> ::bytemuck::Zeroable for UnitInterval<T> where
130        T: UnitIntervalFloat + ::bytemuck::Zeroable
131    {
132    }
133
134    unsafe impl<T> ::bytemuck::NoUninit for UnitInterval<T> where
135        T: UnitIntervalFloat + ::bytemuck::NoUninit
136    {
137    }
138
139    unsafe impl<T> ::bytemuck::CheckedBitPattern for UnitInterval<T>
140    where
141        T: UnitIntervalFloat + ::bytemuck::AnyBitPattern,
142    {
143        type Bits = T;
144
145        #[inline]
146        fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
147            UnitInterval::contains(*bits)
148        }
149    }
150}
151
152#[cfg(feature = "arbitrary")]
153#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
154mod arbitrary {
155    use super::*;
156    use ::arbitrary::{Arbitrary, Result, Unstructured};
157
158    macro_rules! impl_arbitrary_unit_interval {
159        ($float:ty, $unsigned:ty) => {
160            impl<'a> Arbitrary<'a> for UnitInterval<$float> {
161                #[inline]
162                fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
163                    let raw = <$unsigned as Arbitrary<'a>>::arbitrary(u)?;
164                    let value = raw as $float / <$unsigned>::MAX as $float;
165
166                    Ok(Self::from_inner(value))
167                }
168
169                #[inline]
170                fn size_hint(depth: usize) -> (usize, Option<usize>) {
171                    <$unsigned as Arbitrary<'a>>::size_hint(depth)
172                }
173            }
174        };
175    }
176
177    impl_arbitrary_unit_interval!(f32, u32);
178    impl_arbitrary_unit_interval!(f64, u64);
179}
180
181#[cfg(feature = "num-traits")]
182#[cfg_attr(docsrs, doc(cfg(feature = "num-traits")))]
183mod num_traits {
184    use super::*;
185    use ::num_traits::{
186        AsPrimitive, Bounded, ConstOne, FromPrimitive, NumCast, One, Pow, ToBytes, ToPrimitive,
187        ops::{checked::CheckedMul, saturating::SaturatingMul},
188    };
189
190    macro_rules! impl_num_traits_unit_interval {
191        ($float:ty) => {
192            impl ToPrimitive for UnitInterval<$float> {
193                #[inline]
194                fn to_isize(&self) -> Option<isize> {
195                    self.0.to_isize()
196                }
197
198                #[inline]
199                fn to_i8(&self) -> Option<i8> {
200                    self.0.to_i8()
201                }
202
203                #[inline]
204                fn to_i16(&self) -> Option<i16> {
205                    self.0.to_i16()
206                }
207
208                #[inline]
209                fn to_i32(&self) -> Option<i32> {
210                    self.0.to_i32()
211                }
212
213                #[inline]
214                fn to_i64(&self) -> Option<i64> {
215                    self.0.to_i64()
216                }
217
218                #[inline]
219                fn to_i128(&self) -> Option<i128> {
220                    self.0.to_i128()
221                }
222
223                #[inline]
224                fn to_usize(&self) -> Option<usize> {
225                    self.0.to_usize()
226                }
227
228                #[inline]
229                fn to_u8(&self) -> Option<u8> {
230                    self.0.to_u8()
231                }
232
233                #[inline]
234                fn to_u16(&self) -> Option<u16> {
235                    self.0.to_u16()
236                }
237
238                #[inline]
239                fn to_u32(&self) -> Option<u32> {
240                    self.0.to_u32()
241                }
242
243                #[inline]
244                fn to_u64(&self) -> Option<u64> {
245                    self.0.to_u64()
246                }
247
248                #[inline]
249                fn to_u128(&self) -> Option<u128> {
250                    self.0.to_u128()
251                }
252
253                #[inline]
254                fn to_f32(&self) -> Option<f32> {
255                    self.0.to_f32()
256                }
257
258                #[inline]
259                fn to_f64(&self) -> Option<f64> {
260                    self.0.to_f64()
261                }
262            }
263
264            impl FromPrimitive for UnitInterval<$float> {
265                #[inline]
266                fn from_i64(n: i64) -> Option<Self> {
267                    <$float as FromPrimitive>::from_i64(n).and_then(Self::new)
268                }
269
270                #[inline]
271                fn from_u64(n: u64) -> Option<Self> {
272                    <$float as FromPrimitive>::from_u64(n).and_then(Self::new)
273                }
274
275                #[inline]
276                fn from_f32(n: f32) -> Option<Self> {
277                    <$float as FromPrimitive>::from_f32(n).and_then(Self::new)
278                }
279
280                #[inline]
281                fn from_f64(n: f64) -> Option<Self> {
282                    <$float as FromPrimitive>::from_f64(n).and_then(Self::new)
283                }
284            }
285
286            impl NumCast for UnitInterval<$float> {
287                #[inline]
288                fn from<T: ToPrimitive>(n: T) -> Option<Self> {
289                    <$float as NumCast>::from(n).and_then(Self::new)
290                }
291            }
292
293            impl One for UnitInterval<$float> {
294                #[inline]
295                fn one() -> Self {
296                    Self::ONE
297                }
298
299                #[inline]
300                fn is_one(&self) -> bool {
301                    UnitInterval::is_one(*self)
302                }
303            }
304
305            impl ConstOne for UnitInterval<$float> {
306                const ONE: Self = Self::ONE;
307            }
308
309            impl Bounded for UnitInterval<$float> {
310                #[inline]
311                fn min_value() -> Self {
312                    Self::ZERO
313                }
314
315                #[inline]
316                fn max_value() -> Self {
317                    Self::ONE
318                }
319            }
320
321            impl ToBytes for UnitInterval<$float> {
322                type Bytes = <$float as ToBytes>::Bytes;
323
324                #[inline]
325                fn to_be_bytes(&self) -> Self::Bytes {
326                    self.0.to_be_bytes()
327                }
328
329                #[inline]
330                fn to_le_bytes(&self) -> Self::Bytes {
331                    self.0.to_le_bytes()
332                }
333
334                #[inline]
335                fn to_ne_bytes(&self) -> Self::Bytes {
336                    self.0.to_ne_bytes()
337                }
338            }
339
340            impl CheckedMul for UnitInterval<$float> {
341                #[inline]
342                fn checked_mul(&self, v: &Self) -> Option<Self> {
343                    Some(*self * *v)
344                }
345            }
346
347            impl SaturatingMul for UnitInterval<$float> {
348                #[inline]
349                fn saturating_mul(&self, v: &Self) -> Self {
350                    *self * *v
351                }
352            }
353        };
354    }
355
356    macro_rules! impl_pow_unit_interval {
357        ($rhs:ty) => {
358            impl<T: UnitIntervalFloat> Pow<$rhs> for UnitInterval<T> {
359                type Output = Self;
360
361                #[inline]
362                fn pow(self, rhs: $rhs) -> Self::Output {
363                    pow_unit_interval(self, rhs as usize)
364                }
365            }
366
367            impl<T: UnitIntervalFloat> Pow<&$rhs> for UnitInterval<T> {
368                type Output = Self;
369
370                #[inline]
371                fn pow(self, rhs: &$rhs) -> Self::Output {
372                    pow_unit_interval(self, *rhs as usize)
373                }
374            }
375
376            impl<T: UnitIntervalFloat> Pow<$rhs> for &UnitInterval<T> {
377                type Output = UnitInterval<T>;
378
379                #[inline]
380                fn pow(self, rhs: $rhs) -> Self::Output {
381                    pow_unit_interval(*self, rhs as usize)
382                }
383            }
384
385            impl<T: UnitIntervalFloat> Pow<&$rhs> for &UnitInterval<T> {
386                type Output = UnitInterval<T>;
387
388                #[inline]
389                fn pow(self, rhs: &$rhs) -> Self::Output {
390                    pow_unit_interval(*self, *rhs as usize)
391                }
392            }
393        };
394    }
395
396    macro_rules! impl_as_primitive_unit_interval {
397        ($float:ty => $($target:ty),+ $(,)?) => {
398            $(
399                impl AsPrimitive<$target> for UnitInterval<$float> {
400                    #[inline]
401                    fn as_(self) -> $target {
402                        self.0 as $target
403                    }
404                }
405            )+
406        };
407    }
408
409    impl_num_traits_unit_interval!(f32);
410    impl_num_traits_unit_interval!(f64);
411    impl_pow_unit_interval!(u8);
412    impl_pow_unit_interval!(u16);
413    impl_pow_unit_interval!(u32);
414    impl_pow_unit_interval!(usize);
415
416    impl_as_primitive_unit_interval!(f32 => f32, f64);
417    impl_as_primitive_unit_interval!(f64 => f32, f64);
418
419    impl AsPrimitive<UnitInterval<f32>> for UnitInterval<f32> {
420        #[inline]
421        fn as_(self) -> UnitInterval<f32> {
422            self
423        }
424    }
425
426    impl AsPrimitive<UnitInterval<f64>> for UnitInterval<f32> {
427        #[inline]
428        fn as_(self) -> UnitInterval<f64> {
429            UnitInterval::from_inner(self.0 as f64)
430        }
431    }
432
433    impl AsPrimitive<UnitInterval<f32>> for UnitInterval<f64> {
434        #[inline]
435        fn as_(self) -> UnitInterval<f32> {
436            UnitInterval::from_inner(self.0 as f32)
437        }
438    }
439
440    impl AsPrimitive<UnitInterval<f64>> for UnitInterval<f64> {
441        #[inline]
442        fn as_(self) -> UnitInterval<f64> {
443            self
444        }
445    }
446
447    #[inline]
448    fn pow_unit_interval<T: UnitIntervalFloat>(
449        base: UnitInterval<T>,
450        exp: usize,
451    ) -> UnitInterval<T> {
452        let mut result = UnitInterval::ONE;
453        let mut factor = base;
454        let mut exp = exp;
455
456        while exp > 0 {
457            if exp & 1 == 1 {
458                result = result * factor;
459            }
460
461            exp >>= 1;
462
463            if exp > 0 {
464                factor = factor * factor;
465            }
466        }
467
468        result
469    }
470}
471
472impl<T: UnitIntervalFloat> UnitInterval<T> {
473    /// The lower bound of the unit interval.
474    ///
475    /// # Examples
476    ///
477    /// ```
478    /// use unit_intervals::UnitInterval;
479    ///
480    /// assert_eq!(UnitInterval::<f32>::ZERO.get(), 0.0);
481    /// ```
482    pub const ZERO: Self = Self(T::ZERO);
483
484    /// The upper bound of the unit interval.
485    ///
486    /// # Examples
487    ///
488    /// ```
489    /// use unit_intervals::UnitInterval;
490    ///
491    /// assert_eq!(UnitInterval::<f32>::ONE.get(), 1.0);
492    /// ```
493    pub const ONE: Self = Self(T::ONE);
494
495    /// The midpoint of the unit interval.
496    ///
497    /// # Examples
498    ///
499    /// ```
500    /// use unit_intervals::UnitInterval;
501    ///
502    /// assert_eq!(UnitInterval::<f32>::HALF.get(), 0.5);
503    /// ```
504    pub const HALF: Self = Self(T::HALF);
505
506    /// Creates a value if `v` is inside `[0, 1]`.
507    ///
508    /// Returns `None` for values outside the interval and for `NaN`.
509    ///
510    /// # Examples
511    ///
512    /// ```
513    /// use unit_intervals::UnitInterval;
514    ///
515    /// assert_eq!(UnitInterval::<f32>::new(0.25).unwrap().get(), 0.25);
516    /// assert_eq!(UnitInterval::<f32>::new(-0.25), None);
517    /// assert_eq!(UnitInterval::<f32>::new(f32::NAN), None);
518    /// ```
519    #[inline(always)]
520    pub fn new(v: T) -> Option<Self> {
521        if Self::contains(v) {
522            Some(Self::from_inner(v))
523        } else {
524            None
525        }
526    }
527
528    /// Creates a value without checking that `v` is inside `[0, 1]`.
529    ///
530    /// # Safety
531    ///
532    /// The caller must guarantee that `v` is greater than or equal to zero,
533    /// less than or equal to one, and not `NaN`.
534    #[cfg(feature = "unsafe")]
535    #[inline(always)]
536    pub const unsafe fn new_unchecked(v: T) -> Self {
537        Self(v)
538    }
539
540    /// Returns whether `v` is inside `[0, 1]`.
541    ///
542    /// `NaN` is not contained in the interval.
543    ///
544    /// # Examples
545    ///
546    /// ```
547    /// use unit_intervals::UnitInterval;
548    ///
549    /// assert!(UnitInterval::<f32>::contains(0.5));
550    /// assert!(!UnitInterval::<f32>::contains(1.5));
551    /// assert!(!UnitInterval::<f32>::contains(f32::NAN));
552    /// ```
553    #[inline]
554    pub fn contains(v: T) -> bool {
555        v >= T::ZERO && v <= T::ONE
556    }
557
558    /// Creates a value by clamping `v` into `[0, 1]`.
559    ///
560    /// `NaN` is treated as zero.
561    ///
562    /// # Examples
563    ///
564    /// ```
565    /// use unit_intervals::UnitInterval;
566    ///
567    /// assert_eq!(UnitInterval::<f32>::saturating(-0.25).get(), 0.0);
568    /// assert_eq!(UnitInterval::<f32>::saturating(1.25).get(), 1.0);
569    /// assert_eq!(UnitInterval::<f32>::saturating(f32::NAN).get(), 0.0);
570    /// ```
571    #[inline]
572    pub fn saturating(v: T) -> Self {
573        Self::from_inner(v.clamp_unit())
574    }
575
576    #[inline(always)]
577    pub(crate) fn from_inner(v: T) -> Self {
578        Self::assert_contains(v);
579        Self(v)
580    }
581
582    #[cfg(any(test, feature = "assertions"))]
583    #[inline(always)]
584    fn assert_contains(v: T) {
585        assert!(
586            Self::contains(v),
587            "UnitInterval invariant violated: value is outside [0, 1]"
588        );
589    }
590
591    #[cfg(not(any(test, feature = "assertions")))]
592    #[cfg_attr(docsrs, doc(cfg(feature = "assertions")))]
593    #[inline(always)]
594    fn assert_contains(_v: T) {}
595
596    /// Returns the inner floating-point value.
597    ///
598    /// # Examples
599    ///
600    /// ```
601    /// use unit_intervals::UnitInterval;
602    ///
603    /// let value = UnitInterval::new(0.25).unwrap();
604    ///
605    /// assert_eq!(value.get(), 0.25);
606    /// ```
607    #[inline(always)]
608    pub const fn get(self) -> T {
609        self.0
610    }
611
612    /// Consumes the wrapper and returns the inner floating-point value.
613    ///
614    /// # Examples
615    ///
616    /// ```
617    /// use unit_intervals::UnitInterval;
618    ///
619    /// let value = UnitInterval::new(0.25).unwrap();
620    ///
621    /// assert_eq!(value.into_inner(), 0.25);
622    /// ```
623    #[inline(always)]
624    pub const fn into_inner(self) -> T {
625        self.0
626    }
627
628    /// Returns whether this value is exactly zero.
629    ///
630    /// # Examples
631    ///
632    /// ```
633    /// use unit_intervals::UnitInterval;
634    ///
635    /// assert!(UnitInterval::<f32>::ZERO.is_zero());
636    /// assert!(!UnitInterval::<f32>::HALF.is_zero());
637    /// ```
638    #[inline(always)]
639    pub fn is_zero(self) -> bool {
640        self.0 == T::ZERO
641    }
642
643    /// Returns whether this value is exactly one.
644    ///
645    /// # Examples
646    ///
647    /// ```
648    /// use unit_intervals::UnitInterval;
649    ///
650    /// assert!(UnitInterval::<f32>::ONE.is_one());
651    /// assert!(!UnitInterval::<f32>::HALF.is_one());
652    /// ```
653    #[inline(always)]
654    pub fn is_one(self) -> bool {
655        self.0 == T::ONE
656    }
657
658    /// Returns `1 - self`.
659    ///
660    /// # Examples
661    ///
662    /// ```
663    /// use unit_intervals::UnitInterval;
664    ///
665    /// let value = UnitInterval::new(0.25).unwrap();
666    ///
667    /// assert_eq!(value.complement().get(), 0.75);
668    /// ```
669    #[inline(always)]
670    pub fn complement(self) -> Self {
671        Self::from_inner(T::ONE - self.0)
672    }
673
674    /// Returns the smaller of two unit interval values.
675    ///
676    /// # Examples
677    ///
678    /// ```
679    /// use unit_intervals::UnitInterval;
680    ///
681    /// let low = UnitInterval::new(0.25).unwrap();
682    /// let high = UnitInterval::new(0.75).unwrap();
683    ///
684    /// assert_eq!(low.min(high), low);
685    /// ```
686    #[inline]
687    pub fn min(self, rhs: Self) -> Self {
688        if self.0 <= rhs.0 { self } else { rhs }
689    }
690
691    /// Returns the larger of two unit interval values.
692    ///
693    /// # Examples
694    ///
695    /// ```
696    /// use unit_intervals::UnitInterval;
697    ///
698    /// let low = UnitInterval::new(0.25).unwrap();
699    /// let high = UnitInterval::new(0.75).unwrap();
700    ///
701    /// assert_eq!(low.max(high), high);
702    /// ```
703    #[inline]
704    pub fn max(self, rhs: Self) -> Self {
705        if self.0 >= rhs.0 { self } else { rhs }
706    }
707
708    /// Returns the midpoint between two unit interval values.
709    ///
710    /// # Examples
711    ///
712    /// ```
713    /// use unit_intervals::UnitInterval;
714    ///
715    /// let low = UnitInterval::new(0.25).unwrap();
716    /// let high = UnitInterval::new(0.75).unwrap();
717    ///
718    /// assert_eq!(low.midpoint(high).get(), 0.5);
719    /// ```
720    #[inline]
721    pub fn midpoint(self, rhs: Self) -> Self {
722        Self::from_inner((self.0 + rhs.0) * T::HALF)
723    }
724
725    /// Returns the absolute distance between two unit interval values.
726    ///
727    /// # Examples
728    ///
729    /// ```
730    /// use unit_intervals::UnitInterval;
731    ///
732    /// let low = UnitInterval::new(0.25).unwrap();
733    /// let high = UnitInterval::new(0.75).unwrap();
734    ///
735    /// assert_eq!(low.distance_to(high).get(), 0.5);
736    /// assert_eq!(high.distance_to(low).get(), 0.5);
737    /// ```
738    #[inline]
739    pub fn distance_to(self, rhs: Self) -> Self {
740        if self.0 >= rhs.0 {
741            Self::from_inner(self.0 - rhs.0)
742        } else {
743            Self::from_inner(rhs.0 - self.0)
744        }
745    }
746
747    /// Adds two values, returning `None` if the result is outside `[0, 1]`.
748    ///
749    /// # Examples
750    ///
751    /// ```
752    /// use unit_intervals::UnitInterval;
753    ///
754    /// let a = UnitInterval::new(0.25).unwrap();
755    /// let b = UnitInterval::new(0.75).unwrap();
756    ///
757    /// assert_eq!(a.checked_add(a).unwrap().get(), 0.5);
758    /// assert_eq!(b.checked_add(b), None);
759    /// ```
760    #[inline(always)]
761    pub fn checked_add(self, rhs: Self) -> Option<Self> {
762        Self::new(self.0 + rhs.0)
763    }
764
765    /// Adds two values without checking that the result is inside `[0, 1]`.
766    ///
767    /// # Safety
768    ///
769    /// The caller must guarantee that `self + rhs` is inside `[0, 1]` and not
770    /// `NaN`.
771    #[cfg(feature = "unsafe")]
772    #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
773    #[inline(always)]
774    pub unsafe fn add_unchecked(self, rhs: Self) -> Self {
775        // SAFETY: Guaranteed by the caller.
776        unsafe { Self::new_unchecked(self.0 + rhs.0) }
777    }
778
779    /// Adds two values and clamps the result into `[0, 1]`.
780    ///
781    /// # Examples
782    ///
783    /// ```
784    /// use unit_intervals::UnitInterval;
785    ///
786    /// let value = UnitInterval::new(0.75).unwrap();
787    ///
788    /// assert_eq!(value.saturating_add(value).get(), 1.0);
789    /// ```
790    #[inline(always)]
791    pub fn saturating_add(self, rhs: Self) -> Self {
792        Self::saturating(self.0 + rhs.0)
793    }
794
795    /// Subtracts `rhs`, returning `None` if the result is outside `[0, 1]`.
796    ///
797    /// # Examples
798    ///
799    /// ```
800    /// use unit_intervals::UnitInterval;
801    ///
802    /// let low = UnitInterval::new(0.25).unwrap();
803    /// let high = UnitInterval::new(0.75).unwrap();
804    ///
805    /// assert_eq!(high.checked_sub(low).unwrap().get(), 0.5);
806    /// assert_eq!(low.checked_sub(high), None);
807    /// ```
808    #[inline(always)]
809    pub fn checked_sub(self, rhs: Self) -> Option<Self> {
810        Self::new(self.0 - rhs.0)
811    }
812
813    /// Subtracts `rhs` without checking that the result is inside `[0, 1]`.
814    ///
815    /// # Safety
816    ///
817    /// The caller must guarantee that `self - rhs` is inside `[0, 1]` and not
818    /// `NaN`.
819    #[cfg(feature = "unsafe")]
820    #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
821    #[inline(always)]
822    pub unsafe fn sub_unchecked(self, rhs: Self) -> Self {
823        // SAFETY: Guaranteed by the caller.
824        unsafe { Self::new_unchecked(self.0 - rhs.0) }
825    }
826
827    /// Subtracts `rhs` and clamps the result into `[0, 1]`.
828    ///
829    /// # Examples
830    ///
831    /// ```
832    /// use unit_intervals::UnitInterval;
833    ///
834    /// let low = UnitInterval::new(0.25).unwrap();
835    /// let high = UnitInterval::new(0.75).unwrap();
836    ///
837    /// assert_eq!(low.saturating_sub(high).get(), 0.0);
838    /// ```
839    #[inline(always)]
840    pub fn saturating_sub(self, rhs: Self) -> Self {
841        Self::saturating(self.0 - rhs.0)
842    }
843
844    /// Divides by `rhs`, returning `None` if the result is outside `[0, 1]`.
845    ///
846    /// Division by zero follows the backing float semantics and produces
847    /// `None`, because infinity is outside the unit interval.
848    ///
849    /// # Examples
850    ///
851    /// ```
852    /// use unit_intervals::UnitInterval;
853    ///
854    /// let low = UnitInterval::new(0.25).unwrap();
855    /// let high = UnitInterval::new(0.75).unwrap();
856    ///
857    /// assert_eq!(low.checked_div(high).unwrap().get(), 1.0 / 3.0);
858    /// assert_eq!(high.checked_div(low), None);
859    /// assert_eq!(high.checked_div(UnitInterval::ZERO), None);
860    /// ```
861    #[inline(always)]
862    pub fn checked_div(self, rhs: Self) -> Option<Self> {
863        Self::new(self.0 / rhs.0)
864    }
865
866    /// Divides by `rhs` without checking that the result is inside `[0, 1]`.
867    ///
868    /// # Safety
869    ///
870    /// The caller must guarantee that `self / rhs` is inside `[0, 1]` and not
871    /// `NaN`.
872    #[cfg(feature = "unsafe")]
873    #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
874    #[inline(always)]
875    pub unsafe fn div_unchecked(self, rhs: Self) -> Self {
876        // SAFETY: Guaranteed by the caller.
877        unsafe { Self::new_unchecked(self.0 / rhs.0) }
878    }
879
880    /// Divides by `rhs` and clamps the result into `[0, 1]`.
881    ///
882    /// Division by zero follows the backing float semantics and saturates to
883    /// one for positive infinity, or zero for `0 / 0`.
884    ///
885    /// # Examples
886    ///
887    /// ```
888    /// use unit_intervals::UnitInterval;
889    ///
890    /// let low = UnitInterval::new(0.25).unwrap();
891    /// let high = UnitInterval::new(0.75).unwrap();
892    ///
893    /// assert_eq!(high.saturating_div(low).get(), 1.0);
894    /// assert_eq!(low.saturating_div(UnitInterval::ZERO).get(), 1.0);
895    /// ```
896    #[inline(always)]
897    pub fn saturating_div(self, rhs: Self) -> Self {
898        Self::saturating(self.0 / rhs.0)
899    }
900
901    /// Multiplies by an arbitrary float, returning `None` if the result is
902    /// outside `[0, 1]`.
903    ///
904    /// Use the `*` operator when multiplying by another [`UnitInterval`], since
905    /// that operation always stays inside the interval.
906    ///
907    /// # Examples
908    ///
909    /// ```
910    /// use unit_intervals::UnitInterval;
911    ///
912    /// let value = UnitInterval::new(0.25).unwrap();
913    ///
914    /// assert_eq!(value.checked_scale(2.0).unwrap().get(), 0.5);
915    /// assert_eq!(value.checked_scale(8.0), None);
916    /// ```
917    #[inline(always)]
918    pub fn checked_scale(self, factor: T) -> Option<Self> {
919        Self::new(self.0 * factor)
920    }
921
922    /// Multiplies by an arbitrary float without checking that the result is
923    /// inside `[0, 1]`.
924    ///
925    /// # Safety
926    ///
927    /// The caller must guarantee that `self * factor` is inside `[0, 1]` and
928    /// not `NaN`.
929    #[cfg(feature = "unsafe")]
930    #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
931    #[inline(always)]
932    pub unsafe fn scale_unchecked(self, factor: T) -> Self {
933        // SAFETY: Guaranteed by the caller.
934        unsafe { Self::new_unchecked(self.0 * factor) }
935    }
936
937    /// Multiplies by an arbitrary float and clamps the result into `[0, 1]`.
938    ///
939    /// Use the `*` operator when multiplying by another [`UnitInterval`], since
940    /// that operation always stays inside the interval.
941    ///
942    /// # Examples
943    ///
944    /// ```
945    /// use unit_intervals::UnitInterval;
946    ///
947    /// let value = UnitInterval::new(0.75).unwrap();
948    ///
949    /// assert_eq!(value.saturating_scale(2.0).get(), 1.0);
950    /// assert_eq!(value.saturating_scale(-1.0).get(), 0.0);
951    /// ```
952    #[inline(always)]
953    pub fn saturating_scale(self, factor: T) -> Self {
954        Self::saturating(self.0 * factor)
955    }
956
957    /// Linearly interpolates between `start` and `end`.
958    ///
959    /// A value of zero returns `start`, one returns `end`, and values between
960    /// zero and one return the corresponding point between them.
961    ///
962    /// # Examples
963    ///
964    /// ```
965    /// use unit_intervals::UnitInterval;
966    ///
967    /// assert_eq!(UnitInterval::<f32>::ZERO.lerp(10.0, 20.0), 10.0);
968    /// assert_eq!(UnitInterval::<f32>::HALF.lerp(10.0, 20.0), 15.0);
969    /// assert_eq!(UnitInterval::<f32>::ONE.lerp(10.0, 20.0), 20.0);
970    /// ```
971    #[inline]
972    pub fn lerp(self, start: T, end: T) -> T {
973        start + (end - start) * self.0
974    }
975}
976
977/// Returns [`UnitInterval::ZERO`].
978impl<T: UnitIntervalFloat> Default for UnitInterval<T> {
979    #[inline(always)]
980    fn default() -> Self {
981        Self::ZERO
982    }
983}
984
985/// Dereferences to the inner floating-point value.
986impl<T> Deref for UnitInterval<T> {
987    type Target = T;
988
989    #[inline(always)]
990    fn deref(&self) -> &Self::Target {
991        &self.0
992    }
993}
994
995/// Borrows the inner floating-point value.
996impl<T> AsRef<T> for UnitInterval<T> {
997    #[inline(always)]
998    fn as_ref(&self) -> &T {
999        &self.0
1000    }
1001}
1002
1003macro_rules! impl_unit_interval_float {
1004    ($float:ty) => {
1005        impl crate::private::Sealed for $float {}
1006
1007        impl UnitIntervalFloat for $float {
1008            const ZERO: Self = 0.0;
1009            const NEG_ONE: Self = -1.0;
1010            const ONE: Self = 1.0;
1011            const HALF: Self = 0.5;
1012
1013            #[inline]
1014            fn clamp_unit(self) -> Self {
1015                if self.is_nan() {
1016                    return Self::ZERO;
1017                }
1018
1019                self.clamp(Self::ZERO, Self::ONE)
1020            }
1021
1022            #[inline]
1023            fn clamp_signed_unit(self) -> Self {
1024                if self.is_nan() {
1025                    return Self::ZERO;
1026                }
1027
1028                self.clamp(Self::NEG_ONE, Self::ONE)
1029            }
1030        }
1031
1032        impl From<UnitInterval<$float>> for $float {
1033            #[inline(always)]
1034            fn from(u: UnitInterval<$float>) -> Self {
1035                u.0
1036            }
1037        }
1038
1039        impl TryFrom<$float> for UnitInterval<$float> {
1040            type Error = UnitIntervalError;
1041
1042            #[inline]
1043            fn try_from(value: $float) -> Result<Self, Self::Error> {
1044                Self::new(value).ok_or(UnitIntervalError)
1045            }
1046        }
1047
1048        impl PartialEq<$float> for UnitInterval<$float> {
1049            #[inline(always)]
1050            fn eq(&self, other: &$float) -> bool {
1051                self.0 == *other
1052            }
1053        }
1054
1055        impl PartialEq<UnitInterval<$float>> for $float {
1056            #[inline(always)]
1057            fn eq(&self, other: &UnitInterval<$float>) -> bool {
1058                *self == other.0
1059            }
1060        }
1061
1062        impl PartialOrd<$float> for UnitInterval<$float> {
1063            #[inline(always)]
1064            fn partial_cmp(&self, other: &$float) -> Option<Ordering> {
1065                self.0.partial_cmp(other)
1066            }
1067        }
1068
1069        impl PartialOrd<UnitInterval<$float>> for $float {
1070            #[inline(always)]
1071            fn partial_cmp(&self, other: &UnitInterval<$float>) -> Option<Ordering> {
1072                self.partial_cmp(&other.0)
1073            }
1074        }
1075
1076        impl Add for UnitInterval<$float> {
1077            type Output = $float;
1078
1079            #[inline(always)]
1080            fn add(self, rhs: Self) -> Self::Output {
1081                self.0 + rhs.0
1082            }
1083        }
1084
1085        impl Add<$float> for UnitInterval<$float> {
1086            type Output = $float;
1087
1088            #[inline(always)]
1089            fn add(self, rhs: $float) -> Self::Output {
1090                self.0 + rhs
1091            }
1092        }
1093
1094        impl Add<UnitInterval<$float>> for $float {
1095            type Output = $float;
1096
1097            #[inline(always)]
1098            fn add(self, rhs: UnitInterval<$float>) -> Self::Output {
1099                self + rhs.0
1100            }
1101        }
1102
1103        impl Sub for UnitInterval<$float> {
1104            type Output = $float;
1105
1106            #[inline(always)]
1107            fn sub(self, rhs: Self) -> Self::Output {
1108                self.0 - rhs.0
1109            }
1110        }
1111
1112        impl Sub<$float> for UnitInterval<$float> {
1113            type Output = $float;
1114
1115            #[inline(always)]
1116            fn sub(self, rhs: $float) -> Self::Output {
1117                self.0 - rhs
1118            }
1119        }
1120
1121        impl Sub<UnitInterval<$float>> for $float {
1122            type Output = $float;
1123
1124            #[inline(always)]
1125            fn sub(self, rhs: UnitInterval<$float>) -> Self::Output {
1126                self - rhs.0
1127            }
1128        }
1129
1130        impl Mul<$float> for UnitInterval<$float> {
1131            type Output = $float;
1132
1133            #[inline(always)]
1134            fn mul(self, rhs: $float) -> Self::Output {
1135                self.0 * rhs
1136            }
1137        }
1138
1139        impl Mul<UnitInterval<$float>> for $float {
1140            type Output = $float;
1141
1142            #[inline(always)]
1143            fn mul(self, rhs: UnitInterval<$float>) -> Self::Output {
1144                self * rhs.0
1145            }
1146        }
1147
1148        impl Div for UnitInterval<$float> {
1149            type Output = $float;
1150
1151            #[inline(always)]
1152            fn div(self, rhs: Self) -> Self::Output {
1153                self.0 / rhs.0
1154            }
1155        }
1156
1157        impl Div<$float> for UnitInterval<$float> {
1158            type Output = $float;
1159
1160            #[inline(always)]
1161            fn div(self, rhs: $float) -> Self::Output {
1162                self.0 / rhs
1163            }
1164        }
1165
1166        impl Div<UnitInterval<$float>> for $float {
1167            type Output = $float;
1168
1169            #[inline(always)]
1170            fn div(self, rhs: UnitInterval<$float>) -> Self::Output {
1171                self / rhs.0
1172            }
1173        }
1174
1175        impl Rem for UnitInterval<$float> {
1176            type Output = $float;
1177
1178            #[inline(always)]
1179            fn rem(self, rhs: Self) -> Self::Output {
1180                self.0 % rhs.0
1181            }
1182        }
1183
1184        impl Rem<$float> for UnitInterval<$float> {
1185            type Output = $float;
1186
1187            #[inline(always)]
1188            fn rem(self, rhs: $float) -> Self::Output {
1189                self.0 % rhs
1190            }
1191        }
1192
1193        impl Rem<UnitInterval<$float>> for $float {
1194            type Output = $float;
1195
1196            #[inline(always)]
1197            fn rem(self, rhs: UnitInterval<$float>) -> Self::Output {
1198                self % rhs.0
1199            }
1200        }
1201
1202        impl Neg for UnitInterval<$float> {
1203            type Output = $float;
1204
1205            #[inline(always)]
1206            fn neg(self) -> Self::Output {
1207                -self.0
1208            }
1209        }
1210
1211        impl UnitInterval<$float> {
1212            /// Returns the absolute value.
1213            #[inline]
1214            pub fn abs(self) -> Self {
1215                Self::from_inner(self.0.abs())
1216            }
1217
1218            /// Returns a number representing the sign of this value.
1219            #[inline(always)]
1220            pub fn signum(self) -> $float {
1221                self.0.signum()
1222            }
1223
1224            /// Returns this value with the sign of `sign`.
1225            #[inline(always)]
1226            pub fn copysign(self, sign: $float) -> $float {
1227                self.0.copysign(sign)
1228            }
1229
1230            /// Returns `true` if this value is positive zero.
1231            #[inline(always)]
1232            pub fn is_sign_positive(self) -> bool {
1233                self.0.is_sign_positive()
1234            }
1235
1236            /// Returns `true` if this value is negative zero.
1237            #[inline(always)]
1238            pub fn is_sign_negative(self) -> bool {
1239                self.0.is_sign_negative()
1240            }
1241
1242            /// Returns `true`; unit interval values are always finite.
1243            #[inline(always)]
1244            pub fn is_finite(self) -> bool {
1245                self.0.is_finite()
1246            }
1247
1248            /// Returns `false`; unit interval values cannot be infinite.
1249            #[inline(always)]
1250            pub fn is_infinite(self) -> bool {
1251                self.0.is_infinite()
1252            }
1253
1254            /// Returns `false`; unit interval values cannot be `NaN`.
1255            #[inline(always)]
1256            pub fn is_nan(self) -> bool {
1257                self.0.is_nan()
1258            }
1259
1260            /// Takes the reciprocal, `1 / self`.
1261            #[inline(always)]
1262            pub fn recip(self) -> $float {
1263                self.0.recip()
1264            }
1265        }
1266
1267        #[cfg(any(test, feature = "std"))]
1268        impl UnitInterval<$float> {
1269            /// Returns the largest integer less than or equal to this value.
1270            #[inline]
1271            pub fn floor(self) -> Self {
1272                Self::from_inner(self.0.floor())
1273            }
1274
1275            /// Returns the smallest integer greater than or equal to this value.
1276            #[inline]
1277            pub fn ceil(self) -> Self {
1278                Self::from_inner(self.0.ceil())
1279            }
1280
1281            /// Returns the nearest integer to this value, rounding halfway cases away from zero.
1282            #[inline]
1283            pub fn round(self) -> Self {
1284                Self::from_inner(self.0.round())
1285            }
1286
1287            /// Returns the integer part of this value.
1288            #[inline]
1289            pub fn trunc(self) -> Self {
1290                Self::from_inner(self.0.trunc())
1291            }
1292
1293            /// Returns the fractional part of this value.
1294            #[inline]
1295            pub fn fract(self) -> Self {
1296                Self::from_inner(self.0.fract())
1297            }
1298
1299            /// Raises this value to an integer power.
1300            #[inline(always)]
1301            pub fn powi(self, n: i32) -> $float {
1302                self.0.powi(n)
1303            }
1304
1305            /// Raises this value to a floating-point power.
1306            #[inline(always)]
1307            pub fn powf(self, n: $float) -> $float {
1308                self.0.powf(n)
1309            }
1310
1311            /// Returns the square root.
1312            #[inline(always)]
1313            pub fn sqrt(self) -> Self {
1314                Self::from_inner(self.0.sqrt())
1315            }
1316
1317            /// Returns the cube root.
1318            #[inline(always)]
1319            pub fn cbrt(self) -> Self {
1320                Self::from_inner(self.0.cbrt())
1321            }
1322
1323            /// Computes `self * a + b` with one rounding error.
1324            #[inline(always)]
1325            pub fn mul_add(self, a: $float, b: $float) -> $float {
1326                self.0.mul_add(a, b)
1327            }
1328
1329            /// Returns the Euclidean division of this value by `rhs`.
1330            #[inline(always)]
1331            pub fn div_euclid(self, rhs: $float) -> $float {
1332                self.0.div_euclid(rhs)
1333            }
1334
1335            /// Returns the least non-negative remainder of this value divided by `rhs`.
1336            #[inline(always)]
1337            pub fn rem_euclid(self, rhs: $float) -> $float {
1338                self.0.rem_euclid(rhs)
1339            }
1340
1341            /// Returns `e^(self)`.
1342            #[inline(always)]
1343            pub fn exp(self) -> $float {
1344                self.0.exp()
1345            }
1346
1347            /// Returns `2^(self)`.
1348            #[inline(always)]
1349            pub fn exp2(self) -> $float {
1350                self.0.exp2()
1351            }
1352
1353            /// Returns the natural logarithm.
1354            #[inline(always)]
1355            pub fn ln(self) -> $float {
1356                self.0.ln()
1357            }
1358
1359            /// Returns the logarithm with respect to an arbitrary base.
1360            #[inline(always)]
1361            pub fn log(self, base: $float) -> $float {
1362                self.0.log(base)
1363            }
1364
1365            /// Returns the base 2 logarithm.
1366            #[inline(always)]
1367            pub fn log2(self) -> $float {
1368                self.0.log2()
1369            }
1370
1371            /// Returns the base 10 logarithm.
1372            #[inline(always)]
1373            pub fn log10(self) -> $float {
1374                self.0.log10()
1375            }
1376
1377            /// Returns the sine, in radians.
1378            #[inline(always)]
1379            pub fn sin(self) -> $float {
1380                self.0.sin()
1381            }
1382
1383            /// Returns the cosine, in radians.
1384            #[inline(always)]
1385            pub fn cos(self) -> $float {
1386                self.0.cos()
1387            }
1388
1389            /// Returns the tangent, in radians.
1390            #[inline(always)]
1391            pub fn tan(self) -> $float {
1392                self.0.tan()
1393            }
1394
1395            /// Returns both sine and cosine, in radians.
1396            #[inline(always)]
1397            pub fn sin_cos(self) -> ($float, $float) {
1398                self.0.sin_cos()
1399            }
1400
1401            /// Returns the arcsine, in radians.
1402            #[inline(always)]
1403            pub fn asin(self) -> $float {
1404                self.0.asin()
1405            }
1406
1407            /// Returns the arccosine, in radians.
1408            #[inline(always)]
1409            pub fn acos(self) -> $float {
1410                self.0.acos()
1411            }
1412
1413            /// Returns the arctangent, in radians.
1414            #[inline(always)]
1415            pub fn atan(self) -> Self {
1416                Self::from_inner(self.0.atan())
1417            }
1418
1419            /// Returns the four-quadrant arctangent of `self` and `other`, in radians.
1420            #[inline(always)]
1421            pub fn atan2(self, other: $float) -> $float {
1422                self.0.atan2(other)
1423            }
1424
1425            /// Returns the hyperbolic sine.
1426            #[inline(always)]
1427            pub fn sinh(self) -> $float {
1428                self.0.sinh()
1429            }
1430
1431            /// Returns the hyperbolic cosine.
1432            #[inline(always)]
1433            pub fn cosh(self) -> $float {
1434                self.0.cosh()
1435            }
1436
1437            /// Returns the hyperbolic tangent.
1438            #[inline(always)]
1439            pub fn tanh(self) -> Self {
1440                Self::from_inner(self.0.tanh())
1441            }
1442
1443            /// Returns the inverse hyperbolic sine.
1444            #[inline(always)]
1445            pub fn asinh(self) -> Self {
1446                Self::from_inner(self.0.asinh())
1447            }
1448
1449            /// Returns the inverse hyperbolic cosine.
1450            #[inline(always)]
1451            pub fn acosh(self) -> $float {
1452                self.0.acosh()
1453            }
1454
1455            /// Returns the inverse hyperbolic tangent.
1456            #[inline(always)]
1457            pub fn atanh(self) -> $float {
1458                self.0.atanh()
1459            }
1460
1461            /// Calculates the length of the hypotenuse of a right-angle triangle.
1462            #[inline(always)]
1463            pub fn hypot(self, other: $float) -> $float {
1464                self.0.hypot(other)
1465            }
1466        }
1467    };
1468}
1469
1470impl_unit_interval_float!(f32);
1471impl_unit_interval_float!(f64);
1472
1473/// Converts a `UnitInterval<f32>` into its inner value widened to `f64`.
1474impl From<UnitInterval<f32>> for f64 {
1475    #[inline]
1476    fn from(u: UnitInterval) -> Self {
1477        u.0 as f64
1478    }
1479}
1480
1481/// Converts a `UnitInterval<f32>` into `UnitInterval<f64>`.
1482impl From<UnitInterval<f32>> for UnitInterval<f64> {
1483    #[inline]
1484    fn from(u: UnitInterval<f32>) -> Self {
1485        Self::from_inner(u.0 as f64)
1486    }
1487}
1488
1489/// Converts a `UnitInterval<f64>` into `UnitInterval<f32>`.
1490impl From<UnitInterval<f64>> for UnitInterval<f32> {
1491    #[inline]
1492    fn from(u: UnitInterval<f64>) -> Self {
1493        Self::from_inner(u.0 as f32)
1494    }
1495}
1496
1497/// Multiplies two unit interval values.
1498///
1499/// Multiplication is implemented as an operator because the product of two
1500/// values in `[0, 1]` is also in `[0, 1]`.
1501///
1502/// # Examples
1503///
1504/// ```
1505/// use unit_intervals::UnitInterval;
1506///
1507/// let a = UnitInterval::new(0.25).unwrap();
1508/// let b = UnitInterval::new(0.75).unwrap();
1509///
1510/// assert_eq!((a * b).get(), 0.1875);
1511/// ```
1512impl<T: UnitIntervalFloat> Mul for UnitInterval<T> {
1513    type Output = Self;
1514
1515    #[inline]
1516    fn mul(self, rhs: Self) -> Self::Output {
1517        Self::from_inner(self.0 * rhs.0)
1518    }
1519}
1520
1521#[cfg(test)]
1522mod tests {
1523    use super::UnitInterval;
1524
1525    #[test]
1526    #[should_panic(expected = "UnitInterval invariant violated")]
1527    fn test_configuration_enables_internal_assertions() {
1528        UnitInterval::<f32>::from_inner(1.1);
1529    }
1530
1531    #[cfg(feature = "rkyv")]
1532    #[test]
1533    fn rkyv_deserialization_rejects_invalid_archived_inner_value() {
1534        let invalid = super::ArchivedUnitInterval(rkyv::Archived::<f32>::from_native(1.25));
1535
1536        assert!(rkyv::deserialize::<UnitInterval<f32>, rkyv::rancor::Error>(&invalid).is_err());
1537    }
1538}