1use core::{
2 cmp::Ordering,
3 error::Error,
4 fmt,
5 ops::{Add, Deref, Div, Mul, Neg, Rem, Sub},
6};
7
8use crate::{UnitInterval, UnitIntervalError, UnitIntervalFloat};
9
10#[cfg_attr(
15 feature = "rkyv",
16 derive(::rkyv::Archive, ::rkyv::Serialize),
17 rkyv(crate = ::rkyv)
18)]
19#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
20#[repr(transparent)]
21pub struct SignedUnitInterval<T = f32>(T);
22
23#[derive(Debug, Copy, Clone, Eq, PartialEq)]
25pub struct SignedUnitIntervalError;
26
27impl fmt::Display for SignedUnitIntervalError {
28 #[inline]
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.write_str("value is outside the signed unit interval")
31 }
32}
33
34impl Error for SignedUnitIntervalError {}
35
36#[cfg(feature = "rkyv")]
37#[cfg_attr(docsrs, doc(cfg(feature = "rkyv")))]
38mod rkyv {
39 use super::*;
40 use ::rkyv::{
41 Archive, Deserialize,
42 rancor::{Fallible, Source, fail},
43 };
44
45 impl<T, D> Deserialize<SignedUnitInterval<T>, D> for ArchivedSignedUnitInterval<T>
46 where
47 T: Archive + UnitIntervalFloat,
48 T::Archived: Deserialize<T, D>,
49 D: Fallible + ?Sized,
50 D::Error: Source,
51 {
52 #[inline]
53 fn deserialize(&self, deserializer: &mut D) -> Result<SignedUnitInterval<T>, D::Error> {
54 let value = self.0.deserialize(deserializer)?;
55
56 if let Some(value) = SignedUnitInterval::new(value) {
57 Ok(value)
58 } else {
59 fail!(SignedUnitIntervalError);
60 }
61 }
62 }
63}
64
65#[cfg(feature = "serde")]
66#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
67mod serde {
68 use super::*;
69 use ::serde::{Deserialize, Deserializer, Serialize, Serializer, de};
70
71 impl<T: Serialize> Serialize for SignedUnitInterval<T> {
72 #[inline]
73 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
74 self.0.serialize(serializer)
75 }
76 }
77
78 impl<'de, T> Deserialize<'de> for SignedUnitInterval<T>
79 where
80 T: UnitIntervalFloat + Deserialize<'de>,
81 {
82 #[inline]
83 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
84 let value = T::deserialize(deserializer)?;
95
96 Self::new(value).ok_or_else(|| de::Error::custom(SignedUnitIntervalError))
97 }
98 }
99}
100
101#[cfg(feature = "bytemuck")]
102#[cfg_attr(docsrs, doc(cfg(feature = "bytemuck")))]
103mod bytemuck {
104 use super::*;
105
106 unsafe impl<T> ::bytemuck::Zeroable for SignedUnitInterval<T> where
107 T: UnitIntervalFloat + ::bytemuck::Zeroable
108 {
109 }
110
111 unsafe impl<T> ::bytemuck::NoUninit for SignedUnitInterval<T> where
112 T: UnitIntervalFloat + ::bytemuck::NoUninit
113 {
114 }
115
116 unsafe impl<T> ::bytemuck::CheckedBitPattern for SignedUnitInterval<T>
117 where
118 T: UnitIntervalFloat + ::bytemuck::AnyBitPattern,
119 {
120 type Bits = T;
121
122 #[inline]
123 fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
124 SignedUnitInterval::contains(*bits)
125 }
126 }
127}
128
129#[cfg(feature = "arbitrary")]
130#[cfg_attr(docsrs, doc(cfg(feature = "arbitrary")))]
131mod arbitrary {
132 use super::*;
133 use ::arbitrary::{Arbitrary, Result, Unstructured};
134
135 macro_rules! impl_arbitrary_signed_unit_interval {
136 ($float:ty, $unsigned:ty) => {
137 impl<'a> Arbitrary<'a> for SignedUnitInterval<$float> {
138 #[inline]
139 fn arbitrary(u: &mut Unstructured<'a>) -> Result<Self> {
140 let raw = <$unsigned as Arbitrary<'a>>::arbitrary(u)?;
141 let unit = raw as $float / <$unsigned>::MAX as $float;
142 let value = unit * 2.0 - 1.0;
143
144 Ok(Self::from_inner(value))
145 }
146
147 #[inline]
148 fn size_hint(depth: usize) -> (usize, Option<usize>) {
149 <$unsigned as Arbitrary<'a>>::size_hint(depth)
150 }
151 }
152 };
153 }
154
155 impl_arbitrary_signed_unit_interval!(f32, u32);
156 impl_arbitrary_signed_unit_interval!(f64, u64);
157}
158
159#[cfg(feature = "num-traits")]
160#[cfg_attr(docsrs, doc(cfg(feature = "num-traits")))]
161mod num_traits {
162 use super::*;
163 use ::num_traits::{
164 AsPrimitive, Bounded, ConstOne, FromPrimitive, NumCast, One, Pow, ToBytes, ToPrimitive,
165 ops::{
166 checked::{CheckedMul, CheckedNeg},
167 saturating::SaturatingMul,
168 },
169 };
170
171 macro_rules! impl_num_traits_signed_unit_interval {
172 ($float:ty) => {
173 impl ToPrimitive for SignedUnitInterval<$float> {
174 #[inline]
175 fn to_isize(&self) -> Option<isize> {
176 self.0.to_isize()
177 }
178
179 #[inline]
180 fn to_i8(&self) -> Option<i8> {
181 self.0.to_i8()
182 }
183
184 #[inline]
185 fn to_i16(&self) -> Option<i16> {
186 self.0.to_i16()
187 }
188
189 #[inline]
190 fn to_i32(&self) -> Option<i32> {
191 self.0.to_i32()
192 }
193
194 #[inline]
195 fn to_i64(&self) -> Option<i64> {
196 self.0.to_i64()
197 }
198
199 #[inline]
200 fn to_i128(&self) -> Option<i128> {
201 self.0.to_i128()
202 }
203
204 #[inline]
205 fn to_usize(&self) -> Option<usize> {
206 self.0.to_usize()
207 }
208
209 #[inline]
210 fn to_u8(&self) -> Option<u8> {
211 self.0.to_u8()
212 }
213
214 #[inline]
215 fn to_u16(&self) -> Option<u16> {
216 self.0.to_u16()
217 }
218
219 #[inline]
220 fn to_u32(&self) -> Option<u32> {
221 self.0.to_u32()
222 }
223
224 #[inline]
225 fn to_u64(&self) -> Option<u64> {
226 self.0.to_u64()
227 }
228
229 #[inline]
230 fn to_u128(&self) -> Option<u128> {
231 self.0.to_u128()
232 }
233
234 #[inline]
235 fn to_f32(&self) -> Option<f32> {
236 self.0.to_f32()
237 }
238
239 #[inline]
240 fn to_f64(&self) -> Option<f64> {
241 self.0.to_f64()
242 }
243 }
244
245 impl FromPrimitive for SignedUnitInterval<$float> {
246 #[inline]
247 fn from_i64(n: i64) -> Option<Self> {
248 <$float as FromPrimitive>::from_i64(n).and_then(Self::new)
249 }
250
251 #[inline]
252 fn from_u64(n: u64) -> Option<Self> {
253 <$float as FromPrimitive>::from_u64(n).and_then(Self::new)
254 }
255
256 #[inline]
257 fn from_f32(n: f32) -> Option<Self> {
258 <$float as FromPrimitive>::from_f32(n).and_then(Self::new)
259 }
260
261 #[inline]
262 fn from_f64(n: f64) -> Option<Self> {
263 <$float as FromPrimitive>::from_f64(n).and_then(Self::new)
264 }
265 }
266
267 impl NumCast for SignedUnitInterval<$float> {
268 #[inline]
269 fn from<T: ToPrimitive>(n: T) -> Option<Self> {
270 <$float as NumCast>::from(n).and_then(Self::new)
271 }
272 }
273
274 impl One for SignedUnitInterval<$float> {
275 #[inline]
276 fn one() -> Self {
277 Self::ONE
278 }
279
280 #[inline]
281 fn is_one(&self) -> bool {
282 SignedUnitInterval::is_one(*self)
283 }
284 }
285
286 impl ConstOne for SignedUnitInterval<$float> {
287 const ONE: Self = Self::ONE;
288 }
289
290 impl Bounded for SignedUnitInterval<$float> {
291 #[inline]
292 fn min_value() -> Self {
293 Self::NEG_ONE
294 }
295
296 #[inline]
297 fn max_value() -> Self {
298 Self::ONE
299 }
300 }
301
302 impl ToBytes for SignedUnitInterval<$float> {
303 type Bytes = <$float as ToBytes>::Bytes;
304
305 #[inline]
306 fn to_be_bytes(&self) -> Self::Bytes {
307 self.0.to_be_bytes()
308 }
309
310 #[inline]
311 fn to_le_bytes(&self) -> Self::Bytes {
312 self.0.to_le_bytes()
313 }
314
315 #[inline]
316 fn to_ne_bytes(&self) -> Self::Bytes {
317 self.0.to_ne_bytes()
318 }
319 }
320
321 impl CheckedMul for SignedUnitInterval<$float> {
322 #[inline]
323 fn checked_mul(&self, v: &Self) -> Option<Self> {
324 Some(*self * *v)
325 }
326 }
327
328 impl CheckedNeg for SignedUnitInterval<$float> {
329 #[inline]
330 fn checked_neg(&self) -> Option<Self> {
331 Some(-*self)
332 }
333 }
334
335 impl SaturatingMul for SignedUnitInterval<$float> {
336 #[inline]
337 fn saturating_mul(&self, v: &Self) -> Self {
338 *self * *v
339 }
340 }
341 };
342 }
343
344 macro_rules! impl_pow_signed_unit_interval {
345 ($rhs:ty) => {
346 impl<T: UnitIntervalFloat> Pow<$rhs> for SignedUnitInterval<T> {
347 type Output = Self;
348
349 #[inline]
350 fn pow(self, rhs: $rhs) -> Self::Output {
351 pow_signed_unit_interval(self, rhs as usize)
352 }
353 }
354
355 impl<T: UnitIntervalFloat> Pow<&$rhs> for SignedUnitInterval<T> {
356 type Output = Self;
357
358 #[inline]
359 fn pow(self, rhs: &$rhs) -> Self::Output {
360 pow_signed_unit_interval(self, *rhs as usize)
361 }
362 }
363
364 impl<T: UnitIntervalFloat> Pow<$rhs> for &SignedUnitInterval<T> {
365 type Output = SignedUnitInterval<T>;
366
367 #[inline]
368 fn pow(self, rhs: $rhs) -> Self::Output {
369 pow_signed_unit_interval(*self, rhs as usize)
370 }
371 }
372
373 impl<T: UnitIntervalFloat> Pow<&$rhs> for &SignedUnitInterval<T> {
374 type Output = SignedUnitInterval<T>;
375
376 #[inline]
377 fn pow(self, rhs: &$rhs) -> Self::Output {
378 pow_signed_unit_interval(*self, *rhs as usize)
379 }
380 }
381 };
382 }
383
384 macro_rules! impl_as_primitive_signed_unit_interval {
385 ($float:ty => $($target:ty),+ $(,)?) => {
386 $(
387 impl AsPrimitive<$target> for SignedUnitInterval<$float> {
388 #[inline]
389 fn as_(self) -> $target {
390 self.0 as $target
391 }
392 }
393 )+
394 };
395 }
396
397 impl_num_traits_signed_unit_interval!(f32);
398 impl_num_traits_signed_unit_interval!(f64);
399 impl_pow_signed_unit_interval!(u8);
400 impl_pow_signed_unit_interval!(u16);
401 impl_pow_signed_unit_interval!(u32);
402 impl_pow_signed_unit_interval!(usize);
403
404 impl_as_primitive_signed_unit_interval!(f32 => f32, f64);
405 impl_as_primitive_signed_unit_interval!(f64 => f32, f64);
406
407 impl AsPrimitive<SignedUnitInterval<f32>> for SignedUnitInterval<f32> {
408 #[inline]
409 fn as_(self) -> SignedUnitInterval<f32> {
410 self
411 }
412 }
413
414 impl AsPrimitive<SignedUnitInterval<f64>> for SignedUnitInterval<f32> {
415 #[inline]
416 fn as_(self) -> SignedUnitInterval<f64> {
417 SignedUnitInterval::from_inner(self.0 as f64)
418 }
419 }
420
421 impl AsPrimitive<SignedUnitInterval<f32>> for SignedUnitInterval<f64> {
422 #[inline]
423 fn as_(self) -> SignedUnitInterval<f32> {
424 SignedUnitInterval::from_inner(self.0 as f32)
425 }
426 }
427
428 impl AsPrimitive<SignedUnitInterval<f64>> for SignedUnitInterval<f64> {
429 #[inline]
430 fn as_(self) -> SignedUnitInterval<f64> {
431 self
432 }
433 }
434
435 #[inline]
436 fn pow_signed_unit_interval<T: UnitIntervalFloat>(
437 base: SignedUnitInterval<T>,
438 exp: usize,
439 ) -> SignedUnitInterval<T> {
440 let mut result = SignedUnitInterval::ONE;
441 let mut factor = base;
442 let mut exp = exp;
443
444 while exp > 0 {
445 if exp & 1 == 1 {
446 result = result * factor;
447 }
448
449 exp >>= 1;
450
451 if exp > 0 {
452 factor = factor * factor;
453 }
454 }
455
456 result
457 }
458}
459
460impl<T: UnitIntervalFloat> SignedUnitInterval<T> {
461 pub const NEG_ONE: Self = Self(T::NEG_ONE);
463
464 pub const ZERO: Self = Self(T::ZERO);
466
467 pub const ONE: Self = Self(T::ONE);
469
470 pub const HALF: Self = Self(T::HALF);
472
473 #[inline]
477 pub fn new(v: T) -> Option<Self> {
478 if Self::contains(v) {
479 Some(Self::from_inner(v))
480 } else {
481 None
482 }
483 }
484
485 #[cfg(feature = "unsafe")]
492 #[inline]
493 pub const unsafe fn new_unchecked(v: T) -> Self {
494 Self(v)
495 }
496
497 #[inline]
501 pub fn contains(v: T) -> bool {
502 v >= T::NEG_ONE && v <= T::ONE
503 }
504
505 #[inline]
509 pub fn saturating(v: T) -> Self {
510 Self::from_inner(v.clamp_signed_unit())
511 }
512
513 #[inline]
514 pub(crate) fn from_inner(v: T) -> Self {
515 Self::assert_contains(v);
516 Self(v)
517 }
518
519 #[cfg(any(test, feature = "assertions"))]
520 #[inline]
521 fn assert_contains(v: T) {
522 assert!(
523 Self::contains(v),
524 "SignedUnitInterval invariant violated: value is outside [-1, 1]"
525 );
526 }
527
528 #[cfg(not(any(test, feature = "assertions")))]
529 #[cfg_attr(docsrs, doc(cfg(feature = "assertions")))]
530 #[inline]
531 fn assert_contains(_v: T) {}
532
533 #[inline]
535 pub const fn get(self) -> T {
536 self.0
537 }
538
539 #[inline]
541 pub const fn into_inner(self) -> T {
542 self.0
543 }
544
545 #[inline]
547 pub fn is_zero(self) -> bool {
548 self.0 == T::ZERO
549 }
550
551 #[inline]
553 pub fn is_one(self) -> bool {
554 self.0 == T::ONE
555 }
556
557 #[inline]
559 pub fn is_neg_one(self) -> bool {
560 self.0 == T::NEG_ONE
561 }
562
563 #[inline]
565 pub fn complement(self) -> T {
566 T::ONE - self.0
567 }
568
569 #[inline]
571 pub fn min<R: Into<Self>>(self, rhs: R) -> Self {
572 let rhs = rhs.into();
573
574 if self.0 <= rhs.0 { self } else { rhs }
575 }
576
577 #[inline]
579 pub fn max<R: Into<Self>>(self, rhs: R) -> Self {
580 let rhs = rhs.into();
581
582 if self.0 >= rhs.0 { self } else { rhs }
583 }
584
585 #[inline]
587 pub fn midpoint<R: Into<Self>>(self, rhs: R) -> Self {
588 let rhs = rhs.into();
589
590 Self::from_inner((self.0 + rhs.0) * T::HALF)
591 }
592
593 #[inline]
595 pub fn distance_to<R: Into<Self>>(self, rhs: R) -> T {
596 let rhs = rhs.into();
597
598 if self.0 >= rhs.0 {
599 self.0 - rhs.0
600 } else {
601 rhs.0 - self.0
602 }
603 }
604
605 #[inline]
607 pub fn checked_add<R: Into<Self>>(self, rhs: R) -> Option<Self> {
608 Self::new(self.0 + rhs.into().0)
609 }
610
611 #[cfg(feature = "unsafe")]
618 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
619 #[inline]
620 pub unsafe fn add_unchecked<R: Into<Self>>(self, rhs: R) -> Self {
621 unsafe { Self::new_unchecked(self.0 + rhs.into().0) }
623 }
624
625 #[inline]
627 pub fn saturating_add<R: Into<Self>>(self, rhs: R) -> Self {
628 Self::saturating(self.0 + rhs.into().0)
629 }
630
631 #[inline]
633 pub fn checked_sub<R: Into<Self>>(self, rhs: R) -> Option<Self> {
634 Self::new(self.0 - rhs.into().0)
635 }
636
637 #[cfg(feature = "unsafe")]
644 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
645 #[inline]
646 pub unsafe fn sub_unchecked<R: Into<Self>>(self, rhs: R) -> Self {
647 unsafe { Self::new_unchecked(self.0 - rhs.into().0) }
649 }
650
651 #[inline]
653 pub fn saturating_sub<R: Into<Self>>(self, rhs: R) -> Self {
654 Self::saturating(self.0 - rhs.into().0)
655 }
656
657 #[inline]
659 pub fn checked_div<R: Into<Self>>(self, rhs: R) -> Option<Self> {
660 Self::new(self.0 / rhs.into().0)
661 }
662
663 #[cfg(feature = "unsafe")]
670 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
671 #[inline]
672 pub unsafe fn div_unchecked<R: Into<Self>>(self, rhs: R) -> Self {
673 unsafe { Self::new_unchecked(self.0 / rhs.into().0) }
675 }
676
677 #[inline]
679 pub fn saturating_div<R: Into<Self>>(self, rhs: R) -> Self {
680 Self::saturating(self.0 / rhs.into().0)
681 }
682
683 #[inline]
685 pub fn checked_scale(self, factor: T) -> Option<Self> {
686 Self::new(self.0 * factor)
687 }
688
689 #[cfg(feature = "unsafe")]
697 #[cfg_attr(docsrs, doc(cfg(feature = "unsafe")))]
698 #[inline]
699 pub unsafe fn scale_unchecked(self, factor: T) -> Self {
700 unsafe { Self::new_unchecked(self.0 * factor) }
702 }
703
704 #[inline]
706 pub fn saturating_scale(self, factor: T) -> Self {
707 Self::saturating(self.0 * factor)
708 }
709
710 #[inline]
712 pub fn lerp(self, start: T, end: T) -> T {
713 start + (end - start) * self.0
714 }
715}
716
717impl<T: UnitIntervalFloat> Default for SignedUnitInterval<T> {
719 #[inline]
720 fn default() -> Self {
721 Self::ZERO
722 }
723}
724
725impl<T> Deref for SignedUnitInterval<T> {
727 type Target = T;
728
729 #[inline]
730 fn deref(&self) -> &Self::Target {
731 &self.0
732 }
733}
734
735impl<T> AsRef<T> for SignedUnitInterval<T> {
737 #[inline]
738 fn as_ref(&self) -> &T {
739 &self.0
740 }
741}
742
743impl<T: UnitIntervalFloat> From<UnitInterval<T>> for SignedUnitInterval<T> {
744 #[inline]
745 fn from(u: UnitInterval<T>) -> Self {
746 Self::from_inner(u.get())
747 }
748}
749
750impl<T: UnitIntervalFloat> TryFrom<SignedUnitInterval<T>> for UnitInterval<T> {
751 type Error = UnitIntervalError;
752
753 #[inline]
754 fn try_from(value: SignedUnitInterval<T>) -> Result<Self, Self::Error> {
755 Self::new(value.0).ok_or(UnitIntervalError)
756 }
757}
758
759macro_rules! impl_signed_unit_interval_float {
760 ($float:ty) => {
761 impl From<SignedUnitInterval<$float>> for $float {
762 #[inline]
763 fn from(u: SignedUnitInterval<$float>) -> Self {
764 u.0
765 }
766 }
767
768 impl TryFrom<$float> for SignedUnitInterval<$float> {
769 type Error = SignedUnitIntervalError;
770
771 #[inline]
772 fn try_from(value: $float) -> Result<Self, Self::Error> {
773 Self::new(value).ok_or(SignedUnitIntervalError)
774 }
775 }
776
777 impl PartialEq<$float> for SignedUnitInterval<$float> {
778 #[inline]
779 fn eq(&self, other: &$float) -> bool {
780 self.0 == *other
781 }
782 }
783
784 impl PartialEq<SignedUnitInterval<$float>> for $float {
785 #[inline]
786 fn eq(&self, other: &SignedUnitInterval<$float>) -> bool {
787 *self == other.0
788 }
789 }
790
791 impl PartialOrd<$float> for SignedUnitInterval<$float> {
792 #[inline]
793 fn partial_cmp(&self, other: &$float) -> Option<Ordering> {
794 self.0.partial_cmp(other)
795 }
796 }
797
798 impl PartialOrd<SignedUnitInterval<$float>> for $float {
799 #[inline]
800 fn partial_cmp(&self, other: &SignedUnitInterval<$float>) -> Option<Ordering> {
801 self.partial_cmp(&other.0)
802 }
803 }
804
805 impl Add for SignedUnitInterval<$float> {
806 type Output = $float;
807
808 #[inline]
809 fn add(self, rhs: Self) -> Self::Output {
810 self.0 + rhs.0
811 }
812 }
813
814 impl Add<UnitInterval<$float>> for SignedUnitInterval<$float> {
815 type Output = $float;
816
817 #[inline]
818 fn add(self, rhs: UnitInterval<$float>) -> Self::Output {
819 self.0 + rhs.get()
820 }
821 }
822
823 impl Add<SignedUnitInterval<$float>> for UnitInterval<$float> {
824 type Output = $float;
825
826 #[inline]
827 fn add(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
828 self.get() + rhs.0
829 }
830 }
831
832 impl Add<$float> for SignedUnitInterval<$float> {
833 type Output = $float;
834
835 #[inline]
836 fn add(self, rhs: $float) -> Self::Output {
837 self.0 + rhs
838 }
839 }
840
841 impl Add<SignedUnitInterval<$float>> for $float {
842 type Output = $float;
843
844 #[inline]
845 fn add(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
846 self + rhs.0
847 }
848 }
849
850 impl Sub for SignedUnitInterval<$float> {
851 type Output = $float;
852
853 #[inline]
854 fn sub(self, rhs: Self) -> Self::Output {
855 self.0 - rhs.0
856 }
857 }
858
859 impl Sub<UnitInterval<$float>> for SignedUnitInterval<$float> {
860 type Output = $float;
861
862 #[inline]
863 fn sub(self, rhs: UnitInterval<$float>) -> Self::Output {
864 self.0 - rhs.get()
865 }
866 }
867
868 impl Sub<SignedUnitInterval<$float>> for UnitInterval<$float> {
869 type Output = $float;
870
871 #[inline]
872 fn sub(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
873 self.get() - rhs.0
874 }
875 }
876
877 impl Sub<$float> for SignedUnitInterval<$float> {
878 type Output = $float;
879
880 #[inline]
881 fn sub(self, rhs: $float) -> Self::Output {
882 self.0 - rhs
883 }
884 }
885
886 impl Sub<SignedUnitInterval<$float>> for $float {
887 type Output = $float;
888
889 #[inline]
890 fn sub(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
891 self - rhs.0
892 }
893 }
894
895 impl Mul<$float> for SignedUnitInterval<$float> {
896 type Output = $float;
897
898 #[inline]
899 fn mul(self, rhs: $float) -> Self::Output {
900 self.0 * rhs
901 }
902 }
903
904 impl Mul<SignedUnitInterval<$float>> for $float {
905 type Output = $float;
906
907 #[inline]
908 fn mul(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
909 self * rhs.0
910 }
911 }
912
913 impl Div for SignedUnitInterval<$float> {
914 type Output = $float;
915
916 #[inline]
917 fn div(self, rhs: Self) -> Self::Output {
918 self.0 / rhs.0
919 }
920 }
921
922 impl Div<UnitInterval<$float>> for SignedUnitInterval<$float> {
923 type Output = $float;
924
925 #[inline]
926 fn div(self, rhs: UnitInterval<$float>) -> Self::Output {
927 self.0 / rhs.get()
928 }
929 }
930
931 impl Div<SignedUnitInterval<$float>> for UnitInterval<$float> {
932 type Output = $float;
933
934 #[inline]
935 fn div(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
936 self.get() / rhs.0
937 }
938 }
939
940 impl Div<$float> for SignedUnitInterval<$float> {
941 type Output = $float;
942
943 #[inline]
944 fn div(self, rhs: $float) -> Self::Output {
945 self.0 / rhs
946 }
947 }
948
949 impl Div<SignedUnitInterval<$float>> for $float {
950 type Output = $float;
951
952 #[inline]
953 fn div(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
954 self / rhs.0
955 }
956 }
957
958 impl Rem for SignedUnitInterval<$float> {
959 type Output = $float;
960
961 #[inline]
962 fn rem(self, rhs: Self) -> Self::Output {
963 self.0 % rhs.0
964 }
965 }
966
967 impl Rem<UnitInterval<$float>> for SignedUnitInterval<$float> {
968 type Output = $float;
969
970 #[inline]
971 fn rem(self, rhs: UnitInterval<$float>) -> Self::Output {
972 self.0 % rhs.get()
973 }
974 }
975
976 impl Rem<SignedUnitInterval<$float>> for UnitInterval<$float> {
977 type Output = $float;
978
979 #[inline]
980 fn rem(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
981 self.get() % rhs.0
982 }
983 }
984
985 impl Rem<$float> for SignedUnitInterval<$float> {
986 type Output = $float;
987
988 #[inline]
989 fn rem(self, rhs: $float) -> Self::Output {
990 self.0 % rhs
991 }
992 }
993
994 impl Rem<SignedUnitInterval<$float>> for $float {
995 type Output = $float;
996
997 #[inline]
998 fn rem(self, rhs: SignedUnitInterval<$float>) -> Self::Output {
999 self % rhs.0
1000 }
1001 }
1002
1003 impl Neg for SignedUnitInterval<$float> {
1004 type Output = Self;
1005
1006 #[inline]
1007 fn neg(self) -> Self::Output {
1008 Self::from_inner(-self.0)
1009 }
1010 }
1011
1012 impl SignedUnitInterval<$float> {
1013 #[inline]
1015 pub fn abs(self) -> UnitInterval<$float> {
1016 UnitInterval::new(self.0.abs()).expect("absolute signed unit value is in [0, 1]")
1017 }
1018
1019 #[inline]
1021 pub fn signum(self) -> Self {
1022 Self::from_inner(self.0.signum())
1023 }
1024
1025 #[inline]
1027 pub fn copysign(self, sign: $float) -> Self {
1028 Self::from_inner(self.0.copysign(sign))
1029 }
1030
1031 #[inline]
1033 pub fn is_sign_positive(self) -> bool {
1034 self.0.is_sign_positive()
1035 }
1036
1037 #[inline]
1039 pub fn is_sign_negative(self) -> bool {
1040 self.0.is_sign_negative()
1041 }
1042
1043 #[inline]
1045 pub fn is_finite(self) -> bool {
1046 self.0.is_finite()
1047 }
1048
1049 #[inline]
1051 pub fn is_infinite(self) -> bool {
1052 self.0.is_infinite()
1053 }
1054
1055 #[inline]
1057 pub fn is_nan(self) -> bool {
1058 self.0.is_nan()
1059 }
1060
1061 #[inline]
1063 pub fn recip(self) -> $float {
1064 self.0.recip()
1065 }
1066 }
1067
1068 #[cfg(any(test, feature = "std"))]
1069 impl SignedUnitInterval<$float> {
1070 #[inline]
1072 pub fn floor(self) -> Self {
1073 Self::from_inner(self.0.floor())
1074 }
1075
1076 #[inline]
1078 pub fn ceil(self) -> Self {
1079 Self::from_inner(self.0.ceil())
1080 }
1081
1082 #[inline]
1084 pub fn round(self) -> Self {
1085 Self::from_inner(self.0.round())
1086 }
1087
1088 #[inline]
1090 pub fn trunc(self) -> Self {
1091 Self::from_inner(self.0.trunc())
1092 }
1093
1094 #[inline]
1096 pub fn fract(self) -> Self {
1097 Self::from_inner(self.0.fract())
1098 }
1099
1100 #[inline]
1102 pub fn powi(self, n: i32) -> $float {
1103 self.0.powi(n)
1104 }
1105
1106 #[inline]
1108 pub fn powf(self, n: $float) -> $float {
1109 self.0.powf(n)
1110 }
1111
1112 #[inline]
1114 pub fn sqrt(self) -> $float {
1115 self.0.sqrt()
1116 }
1117
1118 #[inline]
1120 pub fn cbrt(self) -> Self {
1121 Self::from_inner(self.0.cbrt())
1122 }
1123
1124 #[inline]
1126 pub fn mul_add(self, a: $float, b: $float) -> $float {
1127 self.0.mul_add(a, b)
1128 }
1129
1130 #[inline]
1132 pub fn div_euclid(self, rhs: $float) -> $float {
1133 self.0.div_euclid(rhs)
1134 }
1135
1136 #[inline]
1138 pub fn rem_euclid(self, rhs: $float) -> $float {
1139 self.0.rem_euclid(rhs)
1140 }
1141
1142 #[inline]
1144 pub fn exp(self) -> $float {
1145 self.0.exp()
1146 }
1147
1148 #[inline]
1150 pub fn exp2(self) -> $float {
1151 self.0.exp2()
1152 }
1153
1154 #[inline]
1156 pub fn ln(self) -> $float {
1157 self.0.ln()
1158 }
1159
1160 #[inline]
1162 pub fn log(self, base: $float) -> $float {
1163 self.0.log(base)
1164 }
1165
1166 #[inline]
1168 pub fn log2(self) -> $float {
1169 self.0.log2()
1170 }
1171
1172 #[inline]
1174 pub fn log10(self) -> $float {
1175 self.0.log10()
1176 }
1177
1178 #[inline]
1180 pub fn sin(self) -> Self {
1181 Self::from_inner(self.0.sin())
1182 }
1183
1184 #[inline]
1186 pub fn cos(self) -> UnitInterval<$float> {
1187 UnitInterval::new(self.0.cos()).expect("cosine on [-1, 1] is in [0, 1]")
1188 }
1189
1190 #[inline]
1192 pub fn tan(self) -> $float {
1193 self.0.tan()
1194 }
1195
1196 #[inline]
1198 pub fn sin_cos(self) -> (Self, UnitInterval<$float>) {
1199 let (sin, cos) = self.0.sin_cos();
1200 (
1201 Self::from_inner(sin),
1202 UnitInterval::new(cos).expect("cosine on [-1, 1] is in [0, 1]"),
1203 )
1204 }
1205
1206 #[inline]
1208 pub fn asin(self) -> $float {
1209 self.0.asin()
1210 }
1211
1212 #[inline]
1214 pub fn acos(self) -> $float {
1215 self.0.acos()
1216 }
1217
1218 #[inline]
1220 pub fn atan(self) -> Self {
1221 Self::from_inner(self.0.atan())
1222 }
1223
1224 #[inline]
1226 pub fn atan2(self, other: $float) -> $float {
1227 self.0.atan2(other)
1228 }
1229
1230 #[inline]
1232 pub fn sinh(self) -> $float {
1233 self.0.sinh()
1234 }
1235
1236 #[inline]
1238 pub fn cosh(self) -> $float {
1239 self.0.cosh()
1240 }
1241
1242 #[inline]
1244 pub fn tanh(self) -> Self {
1245 Self::from_inner(self.0.tanh())
1246 }
1247
1248 #[inline]
1250 pub fn asinh(self) -> Self {
1251 Self::from_inner(self.0.asinh())
1252 }
1253
1254 #[inline]
1256 pub fn acosh(self) -> $float {
1257 self.0.acosh()
1258 }
1259
1260 #[inline]
1262 pub fn atanh(self) -> $float {
1263 self.0.atanh()
1264 }
1265
1266 #[inline]
1268 pub fn hypot(self, other: $float) -> $float {
1269 self.0.hypot(other)
1270 }
1271 }
1272 };
1273}
1274
1275impl_signed_unit_interval_float!(f32);
1276impl_signed_unit_interval_float!(f64);
1277
1278impl From<SignedUnitInterval<f32>> for f64 {
1280 #[inline]
1281 fn from(u: SignedUnitInterval) -> Self {
1282 u.0 as f64
1283 }
1284}
1285
1286impl From<SignedUnitInterval<f32>> for SignedUnitInterval<f64> {
1288 #[inline]
1289 fn from(u: SignedUnitInterval<f32>) -> Self {
1290 Self::from_inner(u.0 as f64)
1291 }
1292}
1293
1294impl From<SignedUnitInterval<f64>> for SignedUnitInterval<f32> {
1296 #[inline]
1297 fn from(u: SignedUnitInterval<f64>) -> Self {
1298 Self::from_inner(u.0 as f32)
1299 }
1300}
1301
1302impl<T: UnitIntervalFloat> Mul for SignedUnitInterval<T> {
1304 type Output = Self;
1305
1306 #[inline]
1307 fn mul(self, rhs: Self) -> Self::Output {
1308 Self::from_inner(self.0 * rhs.0)
1309 }
1310}
1311
1312impl<T: UnitIntervalFloat> Mul<UnitInterval<T>> for SignedUnitInterval<T> {
1314 type Output = Self;
1315
1316 #[inline]
1317 fn mul(self, rhs: UnitInterval<T>) -> Self::Output {
1318 Self::from_inner(self.0 * rhs.get())
1319 }
1320}
1321
1322impl<T: UnitIntervalFloat> Mul<SignedUnitInterval<T>> for UnitInterval<T> {
1324 type Output = SignedUnitInterval<T>;
1325
1326 #[inline]
1327 fn mul(self, rhs: SignedUnitInterval<T>) -> Self::Output {
1328 SignedUnitInterval::from_inner(self.get() * rhs.0)
1329 }
1330}
1331
1332#[cfg(test)]
1333mod tests {
1334 use super::SignedUnitInterval;
1335
1336 #[test]
1337 #[should_panic(expected = "SignedUnitInterval invariant violated")]
1338 fn test_configuration_enables_internal_assertions() {
1339 SignedUnitInterval::<f32>::from_inner(1.1);
1340 }
1341
1342 #[cfg(feature = "rkyv")]
1343 #[test]
1344 fn rkyv_deserialization_rejects_invalid_archived_inner_value() {
1345 let invalid = super::ArchivedSignedUnitInterval(rkyv::Archived::<f32>::from_native(1.25));
1346
1347 assert!(
1348 rkyv::deserialize::<SignedUnitInterval<f32>, rkyv::rancor::Error>(&invalid).is_err()
1349 );
1350 }
1351}