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#[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#[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 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 pub const ZERO: Self = Self(T::ZERO);
483
484 pub const ONE: Self = Self(T::ONE);
494
495 pub const HALF: Self = Self(T::HALF);
505
506 #[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 #[cfg(feature = "unsafe")]
535 #[inline(always)]
536 pub const unsafe fn new_unchecked(v: T) -> Self {
537 Self(v)
538 }
539
540 #[inline]
554 pub fn contains(v: T) -> bool {
555 v >= T::ZERO && v <= T::ONE
556 }
557
558 #[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 #[inline(always)]
608 pub const fn get(self) -> T {
609 self.0
610 }
611
612 #[inline(always)]
624 pub const fn into_inner(self) -> T {
625 self.0
626 }
627
628 #[inline(always)]
639 pub fn is_zero(self) -> bool {
640 self.0 == T::ZERO
641 }
642
643 #[inline(always)]
654 pub fn is_one(self) -> bool {
655 self.0 == T::ONE
656 }
657
658 #[inline(always)]
670 pub fn complement(self) -> Self {
671 Self::from_inner(T::ONE - self.0)
672 }
673
674 #[inline]
687 pub fn min(self, rhs: Self) -> Self {
688 if self.0 <= rhs.0 { self } else { rhs }
689 }
690
691 #[inline]
704 pub fn max(self, rhs: Self) -> Self {
705 if self.0 >= rhs.0 { self } else { rhs }
706 }
707
708 #[inline]
721 pub fn midpoint(self, rhs: Self) -> Self {
722 Self::from_inner((self.0 + rhs.0) * T::HALF)
723 }
724
725 #[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 #[inline(always)]
761 pub fn checked_add(self, rhs: Self) -> Option<Self> {
762 Self::new(self.0 + rhs.0)
763 }
764
765 #[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 unsafe { Self::new_unchecked(self.0 + rhs.0) }
777 }
778
779 #[inline(always)]
791 pub fn saturating_add(self, rhs: Self) -> Self {
792 Self::saturating(self.0 + rhs.0)
793 }
794
795 #[inline(always)]
809 pub fn checked_sub(self, rhs: Self) -> Option<Self> {
810 Self::new(self.0 - rhs.0)
811 }
812
813 #[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 unsafe { Self::new_unchecked(self.0 - rhs.0) }
825 }
826
827 #[inline(always)]
840 pub fn saturating_sub(self, rhs: Self) -> Self {
841 Self::saturating(self.0 - rhs.0)
842 }
843
844 #[inline(always)]
862 pub fn checked_div(self, rhs: Self) -> Option<Self> {
863 Self::new(self.0 / rhs.0)
864 }
865
866 #[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 unsafe { Self::new_unchecked(self.0 / rhs.0) }
878 }
879
880 #[inline(always)]
897 pub fn saturating_div(self, rhs: Self) -> Self {
898 Self::saturating(self.0 / rhs.0)
899 }
900
901 #[inline(always)]
918 pub fn checked_scale(self, factor: T) -> Option<Self> {
919 Self::new(self.0 * factor)
920 }
921
922 #[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 unsafe { Self::new_unchecked(self.0 * factor) }
935 }
936
937 #[inline(always)]
953 pub fn saturating_scale(self, factor: T) -> Self {
954 Self::saturating(self.0 * factor)
955 }
956
957 #[inline]
972 pub fn lerp(self, start: T, end: T) -> T {
973 start + (end - start) * self.0
974 }
975}
976
977impl<T: UnitIntervalFloat> Default for UnitInterval<T> {
979 #[inline(always)]
980 fn default() -> Self {
981 Self::ZERO
982 }
983}
984
985impl<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
995impl<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 #[inline]
1214 pub fn abs(self) -> Self {
1215 Self::from_inner(self.0.abs())
1216 }
1217
1218 #[inline(always)]
1220 pub fn signum(self) -> $float {
1221 self.0.signum()
1222 }
1223
1224 #[inline(always)]
1226 pub fn copysign(self, sign: $float) -> $float {
1227 self.0.copysign(sign)
1228 }
1229
1230 #[inline(always)]
1232 pub fn is_sign_positive(self) -> bool {
1233 self.0.is_sign_positive()
1234 }
1235
1236 #[inline(always)]
1238 pub fn is_sign_negative(self) -> bool {
1239 self.0.is_sign_negative()
1240 }
1241
1242 #[inline(always)]
1244 pub fn is_finite(self) -> bool {
1245 self.0.is_finite()
1246 }
1247
1248 #[inline(always)]
1250 pub fn is_infinite(self) -> bool {
1251 self.0.is_infinite()
1252 }
1253
1254 #[inline(always)]
1256 pub fn is_nan(self) -> bool {
1257 self.0.is_nan()
1258 }
1259
1260 #[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 #[inline]
1271 pub fn floor(self) -> Self {
1272 Self::from_inner(self.0.floor())
1273 }
1274
1275 #[inline]
1277 pub fn ceil(self) -> Self {
1278 Self::from_inner(self.0.ceil())
1279 }
1280
1281 #[inline]
1283 pub fn round(self) -> Self {
1284 Self::from_inner(self.0.round())
1285 }
1286
1287 #[inline]
1289 pub fn trunc(self) -> Self {
1290 Self::from_inner(self.0.trunc())
1291 }
1292
1293 #[inline]
1295 pub fn fract(self) -> Self {
1296 Self::from_inner(self.0.fract())
1297 }
1298
1299 #[inline(always)]
1301 pub fn powi(self, n: i32) -> $float {
1302 self.0.powi(n)
1303 }
1304
1305 #[inline(always)]
1307 pub fn powf(self, n: $float) -> $float {
1308 self.0.powf(n)
1309 }
1310
1311 #[inline(always)]
1313 pub fn sqrt(self) -> Self {
1314 Self::from_inner(self.0.sqrt())
1315 }
1316
1317 #[inline(always)]
1319 pub fn cbrt(self) -> Self {
1320 Self::from_inner(self.0.cbrt())
1321 }
1322
1323 #[inline(always)]
1325 pub fn mul_add(self, a: $float, b: $float) -> $float {
1326 self.0.mul_add(a, b)
1327 }
1328
1329 #[inline(always)]
1331 pub fn div_euclid(self, rhs: $float) -> $float {
1332 self.0.div_euclid(rhs)
1333 }
1334
1335 #[inline(always)]
1337 pub fn rem_euclid(self, rhs: $float) -> $float {
1338 self.0.rem_euclid(rhs)
1339 }
1340
1341 #[inline(always)]
1343 pub fn exp(self) -> $float {
1344 self.0.exp()
1345 }
1346
1347 #[inline(always)]
1349 pub fn exp2(self) -> $float {
1350 self.0.exp2()
1351 }
1352
1353 #[inline(always)]
1355 pub fn ln(self) -> $float {
1356 self.0.ln()
1357 }
1358
1359 #[inline(always)]
1361 pub fn log(self, base: $float) -> $float {
1362 self.0.log(base)
1363 }
1364
1365 #[inline(always)]
1367 pub fn log2(self) -> $float {
1368 self.0.log2()
1369 }
1370
1371 #[inline(always)]
1373 pub fn log10(self) -> $float {
1374 self.0.log10()
1375 }
1376
1377 #[inline(always)]
1379 pub fn sin(self) -> $float {
1380 self.0.sin()
1381 }
1382
1383 #[inline(always)]
1385 pub fn cos(self) -> $float {
1386 self.0.cos()
1387 }
1388
1389 #[inline(always)]
1391 pub fn tan(self) -> $float {
1392 self.0.tan()
1393 }
1394
1395 #[inline(always)]
1397 pub fn sin_cos(self) -> ($float, $float) {
1398 self.0.sin_cos()
1399 }
1400
1401 #[inline(always)]
1403 pub fn asin(self) -> $float {
1404 self.0.asin()
1405 }
1406
1407 #[inline(always)]
1409 pub fn acos(self) -> $float {
1410 self.0.acos()
1411 }
1412
1413 #[inline(always)]
1415 pub fn atan(self) -> Self {
1416 Self::from_inner(self.0.atan())
1417 }
1418
1419 #[inline(always)]
1421 pub fn atan2(self, other: $float) -> $float {
1422 self.0.atan2(other)
1423 }
1424
1425 #[inline(always)]
1427 pub fn sinh(self) -> $float {
1428 self.0.sinh()
1429 }
1430
1431 #[inline(always)]
1433 pub fn cosh(self) -> $float {
1434 self.0.cosh()
1435 }
1436
1437 #[inline(always)]
1439 pub fn tanh(self) -> Self {
1440 Self::from_inner(self.0.tanh())
1441 }
1442
1443 #[inline(always)]
1445 pub fn asinh(self) -> Self {
1446 Self::from_inner(self.0.asinh())
1447 }
1448
1449 #[inline(always)]
1451 pub fn acosh(self) -> $float {
1452 self.0.acosh()
1453 }
1454
1455 #[inline(always)]
1457 pub fn atanh(self) -> $float {
1458 self.0.atanh()
1459 }
1460
1461 #[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
1473impl From<UnitInterval<f32>> for f64 {
1475 #[inline]
1476 fn from(u: UnitInterval) -> Self {
1477 u.0 as f64
1478 }
1479}
1480
1481impl 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
1489impl 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
1497impl<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}