1use std::num::Wrapping;
4use std::ops::*;
5use std::cmp;
6use num_traits::{Zero, One, FloatConst};
7
8pub use num_traits::ops::mul_add::MulAdd;
9
10#[allow(unused_imports)]
12use num_traits::real::Real;
13
14pub fn partial_min<T: PartialOrd + Sized>(a: T, b: T) -> T {
16 if a <= b { a } else { b }
17}
18pub fn partial_max<T: PartialOrd + Sized>(a: T, b: T) -> T {
20 if a >= b { a } else { b }
21}
22
23pub trait IsBetween<Bound=Self>: Sized {
25 type Output;
27 fn is_between(self, lower: Bound, upper: Bound) -> Self::Output;
42 fn is_between01(self) -> Self::Output where Bound: Zero + One {
44 self.is_between(Bound::zero(), Bound::one())
45 }
46 fn is_between_inclusive_range_bounds(self, range: RangeInclusive<Bound>) -> Self::Output {
49 let (start, end) = range.into_inner();
50 self.is_between(start, end)
51 }
52}
53
54pub trait IsBetween01: IsBetween + Zero + One {}
56impl<T: IsBetween + Zero + One> IsBetween01 for T {}
57
58
59pub trait Clamp<Bound=Self>: Sized {
61 fn clamped(self, lower: Bound, upper: Bound) -> Self;
76 fn clamped_to_inclusive_range(self, range: RangeInclusive<Bound>) -> Self {
78 let (start, end) = range.into_inner();
79 self.clamped(start, end)
80 }
81 fn clamp(val: Self, lower: Bound, upper: Bound) -> Self {
86 val.clamped(lower, upper)
87 }
88 fn clamp_to_inclusive_range(val: Self, range: RangeInclusive<Bound>) -> Self {
90 let (start, end) = range.into_inner();
91 Self::clamp(val, start, end)
92 }
93 fn clamped01(self) -> Self where Bound: Zero + One {
95 self.clamped(Bound::zero(), Bound::one())
96 }
97 fn clamp01(val: Self) -> Self where Bound: Zero + One {
99 Self::clamp(val, Bound::zero(), Bound::one())
100 }
101 fn clamped_minus1_1(self) -> Self where Bound: One + Neg<Output=Bound> {
103 self.clamped(-Bound::one(), Bound::one())
104 }
105 fn clamp_minus1_1(val: Self) -> Self where Bound: One + Neg<Output=Bound> {
107 Self::clamp(val, -Bound::one(), Bound::one())
108 }
109}
110
111pub trait Clamp01: Clamp + Zero + One {}
113impl<T: Clamp + Zero + One> Clamp01 for T {}
114
115pub trait ClampMinus1: Clamp + One + Neg<Output=Self> {}
117impl<T: Clamp + One + Neg<Output=T>> ClampMinus1 for T {}
118
119macro_rules! impl_clamp_float {
120 ($($T:ty)+) => {
121 $(
122 impl Clamp for $T {
123 fn clamped(self, lower: Self, upper: Self) -> Self {
124 assert!(lower <= upper);
125 partial_min(partial_max(self, lower), upper)
126 }
127 }
128 impl IsBetween for $T {
129 type Output = bool;
130 fn is_between(self, lower: Self, upper: Self) -> bool {
131 assert!(lower <= upper);
132 lower <= self && self <= upper
133 }
134 }
135 )+
136 }
137}
138macro_rules! impl_clamp_integer {
139 ($($T:ty)+) => {
140 $(
141 impl Clamp for $T {
142 fn clamped(self, lower: Self, upper: Self) -> Self {
143 assert!(lower <= upper);
144 cmp::min(cmp::max(self, lower), upper)
145 }
146 }
147 impl IsBetween for $T {
148 type Output = bool;
149 fn is_between(self, lower: Self, upper: Self) -> bool {
150 assert!(lower <= upper);
151 lower <= self && self <= upper
152 }
153 }
154 )+
155 }
156}
157
158impl_clamp_float!{
159 f32 f64
160}
161impl_clamp_integer!{
162 i8 i16 i32 i64 isize u8 u16 u32 u64 usize
163 Wrapping<i8>
164 Wrapping<i16>
165 Wrapping<i32>
166 Wrapping<i64>
167 Wrapping<isize>
168 Wrapping<u8>
169 Wrapping<u16>
170 Wrapping<u32>
171 Wrapping<u64>
172 Wrapping<usize>
173}
174
175
176#[deprecated(since = "0.15.0", note = "This is redundant with num-trait's MulAdd trait and std's mul_add operation")]
178pub fn mul_add<Output,V,M,A>(val: V, mul: M, add: A) -> Output where V: MulAdd<M,A,Output=Output> {
179 val.mul_add(mul, add)
180}
181
182
183pub trait Lerp<Factor=f32>: Sized
231{
232 type Output;
234 fn lerp_unclamped(from: Self, to: Self, factor: Factor) -> Self::Output;
251
252 fn lerp_unclamped_inclusive_range(range: RangeInclusive<Self>, factor: Factor) -> Self::Output {
254 let (from, to) = range.into_inner();
255 Self::lerp_unclamped(from, to, factor)
256 }
257
258 fn lerp_unclamped_precise(from: Self, to: Self, factor: Factor) -> Self::Output {
275 Self::lerp_unclamped(from, to, factor)
276 }
277
278 fn lerp_unclamped_precise_inclusive_range(range: RangeInclusive<Self>, factor: Factor) -> Self::Output {
280 let (from, to) = range.into_inner();
281 Self::lerp_unclamped_precise(from, to, factor)
282 }
283
284 fn lerp(from: Self, to: Self, factor: Factor) -> Self::Output where Factor: Clamp + Zero + One {
298 Self::lerp_unclamped(from, to, factor.clamped01())
299 }
300
301 fn lerp_inclusive_range(range: RangeInclusive<Self>, factor: Factor) -> Self::Output where Factor: Clamp + Zero + One {
303 let (from, to) = range.into_inner();
304 Self::lerp(from, to, factor)
305 }
306
307 fn lerp_precise(from: Self, to: Self, factor: Factor) -> Self::Output where Factor: Clamp + Zero + One {
321 Self::lerp_unclamped_precise(from, to, factor.clamped01())
322 }
323
324 fn lerp_precise_inclusive_range(range: RangeInclusive<Self>, factor: Factor) -> Self::Output where Factor: Clamp + Zero + One {
326 let (from, to) = range.into_inner();
327 Self::lerp_precise(from, to, factor)
328 }
329}
330
331macro_rules! lerp_impl_float {
332 ($($T:ty)+) => {
333 $(
334 impl Lerp<$T> for $T {
335 type Output = $T;
336 fn lerp_unclamped_precise(from: Self, to: Self, factor: Self) -> Self {
337 from*(Self::one()-factor) + to*factor
338 }
339 fn lerp_unclamped(from: Self, to: Self, factor: Self) -> Self {
340 self::MulAdd::mul_add(factor, to - from, from)
341 }
342 }
343 impl<'a> Lerp<$T> for &'a $T {
344 type Output = $T;
345 fn lerp_unclamped_precise(from: Self, to: Self, factor: $T) -> $T {
346 Lerp::lerp_unclamped_precise(*from, *to, factor)
347 }
348 fn lerp_unclamped(from: Self, to: Self, factor: $T) -> $T {
349 Lerp::lerp_unclamped(*from, *to, factor)
350 }
351 }
352 )+
353 }
354}
355macro_rules! lerp_impl_integer {
356 ($($T:ty)+) => {
357 $(
358 impl Lerp<f32> for $T {
359 type Output = $T;
360 fn lerp_unclamped_precise(from: Self, to: Self, factor: f32) -> Self {
361 num_traits::Float::round((from as f32)*((1f32)-factor) + (to as f32)*factor) as Self
362 }
363 fn lerp_unclamped(from: Self, to: Self, factor: f32) -> Self {
364 num_traits::Float::round(self::MulAdd::mul_add(factor, (to - from) as f32, from as f32)) as Self
365 }
366 }
367 impl Lerp<f64> for $T {
368 type Output = $T;
369 fn lerp_unclamped_precise(from: Self, to: Self, factor: f64) -> Self {
370 num_traits::Float::round((from as f64)*((1f64)-factor) + (to as f64)*factor) as Self
371 }
372 fn lerp_unclamped(from: Self, to: Self, factor: f64) -> Self {
373 num_traits::Float::round(self::MulAdd::mul_add(factor, (to - from) as f64, from as f64)) as Self
374 }
375 }
376 impl<'a> Lerp<f32> for &'a $T {
377 type Output = $T;
378 fn lerp_unclamped_precise(from: Self, to: Self, factor: f32) -> $T {
379 Lerp::lerp_unclamped_precise(*from, *to, factor)
380 }
381 fn lerp_unclamped(from: Self, to: Self, factor: f32) -> $T {
382 Lerp::lerp_unclamped(*from, *to, factor)
383 }
384 }
385 impl<'a> Lerp<f64> for &'a $T {
386 type Output = $T;
387 fn lerp_unclamped_precise(from: Self, to: Self, factor: f64) -> $T {
388 Lerp::lerp_unclamped_precise(*from, *to, factor)
389 }
390 fn lerp_unclamped(from: Self, to: Self, factor: f64) -> $T {
391 Lerp::lerp_unclamped(*from, *to, factor)
392 }
393 }
394 )+
395 }
396}
397
398lerp_impl_float!{f32 f64}
399lerp_impl_integer!{
400 i8 i16 i32 i64 isize u8 u16 u32 u64 usize
401 }
414
415pub trait Slerp<Factor=f32>: Sized {
419 type Output;
421 fn slerp_unclamped(from: Self, to: Self, factor: Factor) -> Self::Output;
424 fn slerp(from: Self, to: Self, factor: Factor) -> Self::Output where Factor: Clamp + Zero + One {
427 Self::slerp_unclamped(from, to, factor.clamped01())
428 }
429}
430
431pub trait Wrap<Bound=Self>: Sized {
433 fn wrapped(self, upper: Bound) -> Self;
468 fn wrap(val: Self, upper: Bound) -> Self {
473 val.wrapped(upper)
474 }
475 fn wrapped_2pi(self) -> Self where Bound: FloatConst + Add<Output=Bound> {
480 self.wrapped(Bound::PI() + Bound::PI())
481 }
482 fn wrap_2pi(val: Self) -> Self where Bound: FloatConst + Add<Output=Bound> {
487 val.wrapped_2pi()
488 }
489
490 fn wrapped_between(self, lower: Bound, upper: Bound) -> Self;
514 fn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
519 where Self: Sub<Output=Self> + Add<Output=Self> + From<Bound>,
520 Bound: Copy + Sub<Output=Bound> + PartialOrd
521 {
522 val.wrapped_between(lower, upper)
523 }
524 fn pingpong(self, upper: Bound) -> Self;
546
547 fn delta_angle(self, target: Self) -> Self
549 where Self: From<Bound> + Sub<Output=Self> + PartialOrd,
550 Bound: FloatConst + Add<Output=Bound>
551 {
552 let num = Self::wrap(target - self, Bound::PI() + Bound::PI());
553 if num > Self::from(Bound::PI()) {
554 return num - Self::from(Bound::PI() + Bound::PI());
555 }
556 num
557 }
558 fn delta_angle_degrees(self, target: Self) -> Self
562 where Self: From<Bound> + Sub<Output=Self> + PartialOrd,
563 Bound: From<u16>
564 {
565 let num = Self::wrap(target - self, Bound::from(360));
566 if num > Self::from(Bound::from(180)) {
567 return num - Self::from(Bound::from(360));
568 }
569 num
570 }
571
572}
573
574macro_rules! wrap_impl_float {
575 ($($T:ty)+) => {
576 $(
577 impl Wrap for $T {
578 fn wrapped(self, upper: Self) -> Self {
579 assert!(upper > Self::zero());
580 self - num_traits::Float::floor(self/upper) * upper
582 }
583 fn wrapped_between(self, lower: Self, upper: Self) -> Self {
584 assert!(lower < upper);
585 assert!(lower >= Self::zero());
586 assert!(upper > Self::zero());
587 let out = self - lower;
588 let out = out.wrapped(upper - lower);
589 out + lower
590 }
591 fn pingpong(self, upper: Self) -> Self {
592 assert!(upper > Self::zero());
593 let t = self.wrapped(upper + upper);
595 let upper = || Self::from(upper);
596 upper() - num_traits::Float::abs(t - upper())
597 }
598 }
599 )+
600 }
601}
602macro_rules! wrap_impl_uint {
603 ($($T:ty)+) => {
604 $(
605 impl Wrap for $T {
606 fn wrapped_between(mut self, lower: Self, upper: Self) -> Self {
608 assert!(lower < upper);
609 assert!(lower >= Self::zero());
610 assert!(upper > Self::zero());
611 let range_size = upper - lower ;
612 if self < lower {
613 self += range_size * ((lower-self)/range_size + Self::one());
614 }
615 lower + (self - lower) % range_size
616 }
617 fn wrapped(self, upper: Self) -> Self {
618 assert!(upper > Self::zero());
619 self % upper
620 }
621 fn pingpong(self, upper: Self) -> Self {
622 assert!(upper > Self::zero());
623 let r = self % (upper+upper);
624 if r < upper {
625 r
626 } else {
627 upper+upper-r
628 }
629 }
630 }
631 )+
632 }
633}
634macro_rules! wrap_impl_sint {
635 ($($T:ty)+) => {
636 $(
637 impl Wrap for $T {
638 fn wrapped_between(mut self, lower: Self, upper: Self) -> Self {
640 assert!(lower < upper);
641 assert!(lower >= Self::zero());
642 assert!(upper > Self::zero());
643 let range_size = upper - lower ;
644 if self < lower {
645 self += range_size * ((lower-self)/range_size + Self::one());
646 }
647 lower + (self - lower) % range_size
648 }
649 fn wrapped(self, upper: Self) -> Self {
650 assert!(upper > Self::zero());
651 self.wrapped_between(Self::zero(), upper)
652 }
653 fn pingpong(self, upper: Self) -> Self {
654 assert!(upper > Self::zero());
655 let r = self.wrapped(upper+upper);
656 if r <= upper {
657 r
658 } else {
659 upper+upper-r
660 }
661 }
662 }
663 )+
664 }
665}
666
667wrap_impl_float!{f32 f64}
668wrap_impl_uint!{
669 u8 u16 u32 u64 usize
670 Wrapping<u8>
671 Wrapping<u16>
672 Wrapping<u32>
673 Wrapping<u64>
674 Wrapping<usize>
675}
676wrap_impl_sint!{
677 i8 i16 i32 i64 isize
678 Wrapping<i8>
679 Wrapping<i16>
680 Wrapping<i32>
681 Wrapping<i64>
682 Wrapping<isize>
683}
684
685pub trait ColorComponent : Zero {
687 fn full() -> Self;
691}
692
693impl ColorComponent for f32 { fn full() -> Self { 1f32 } }
694impl ColorComponent for f64 { fn full() -> Self { 1f64 } }
695impl ColorComponent for u8 { fn full() -> Self { std::u8 ::MAX } }
696impl ColorComponent for u16 { fn full() -> Self { std::u16 ::MAX } }
697impl ColorComponent for u32 { fn full() -> Self { std::u32 ::MAX } }
698impl ColorComponent for u64 { fn full() -> Self { std::u64 ::MAX } }
699impl ColorComponent for i8 { fn full() -> Self { std::i8 ::MAX } }
701impl ColorComponent for i16 { fn full() -> Self { std::i16 ::MAX } }
702impl ColorComponent for i32 { fn full() -> Self { std::i32 ::MAX } }
703impl ColorComponent for i64 { fn full() -> Self { std::i64 ::MAX } }
704impl ColorComponent for Wrapping<u8 > { fn full() -> Self { Wrapping(ColorComponent::full()) } }
706impl ColorComponent for Wrapping<u16> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
707impl ColorComponent for Wrapping<u32> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
708impl ColorComponent for Wrapping<u64> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
709impl ColorComponent for Wrapping<i8 > { fn full() -> Self { Wrapping(ColorComponent::full()) } }
711impl ColorComponent for Wrapping<i16> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
712impl ColorComponent for Wrapping<i32> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
713impl ColorComponent for Wrapping<i64> { fn full() -> Self { Wrapping(ColorComponent::full()) } }
714#[cfg(test)]
718mod tests {
719 use super::*;
720
721 macro_rules! for_each_unsigned_type {
722 ($($T:ident)+) => {
723 $(mod $T {
724 use super::Wrap;
725 #[test]
726 fn wrapped() {
727 assert_eq!((0 as $T).wrapped(3 as $T), 0 as $T);
728 assert_eq!((1 as $T).wrapped(3 as $T), 1 as $T);
729 assert_eq!((2 as $T).wrapped(3 as $T), 2 as $T);
730 assert_eq!((3 as $T).wrapped(3 as $T), 0 as $T);
731 assert_eq!((4 as $T).wrapped(3 as $T), 1 as $T);
732 assert_eq!((5 as $T).wrapped(3 as $T), 2 as $T);
733 }
734 #[test]
735 fn wrapped_between() {
736 assert_eq!((0 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
737 assert_eq!((1 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
738 assert_eq!((2 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
739 assert_eq!((3 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
740 assert_eq!((4 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
741 assert_eq!((5 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
742 assert_eq!((6 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
743 }
744 #[test]
745 fn pingpong() {
746 assert_eq!((0 as $T).pingpong(3 as $T), 0 as $T);
747 assert_eq!((1 as $T).pingpong(3 as $T), 1 as $T);
748 assert_eq!((2 as $T).pingpong(3 as $T), 2 as $T);
749 assert_eq!((3 as $T).pingpong(3 as $T), 3 as $T);
750 assert_eq!((4 as $T).pingpong(3 as $T), 2 as $T);
751 assert_eq!((5 as $T).pingpong(3 as $T), 1 as $T);
752 assert_eq!((6 as $T).pingpong(3 as $T), 0 as $T);
753 assert_eq!((7 as $T).pingpong(3 as $T), 1 as $T);
754 }
755 })+
756 };
757 }
758
759 macro_rules! for_each_signed_type {
760 ($($T:ident)+) => {
761 $(mod $T {
762 use super::Wrap;
763 #[test]
764 fn wrapped() {
765 assert_eq!((-5 as $T).wrapped(3 as $T), 1 as $T);
766 assert_eq!((-4 as $T).wrapped(3 as $T), 2 as $T);
767 assert_eq!((-3 as $T).wrapped(3 as $T), 0 as $T);
768 assert_eq!((-2 as $T).wrapped(3 as $T), 1 as $T);
769 assert_eq!((-1 as $T).wrapped(3 as $T), 2 as $T);
770 assert_eq!(( 0 as $T).wrapped(3 as $T), 0 as $T);
771 assert_eq!(( 1 as $T).wrapped(3 as $T), 1 as $T);
772 assert_eq!(( 2 as $T).wrapped(3 as $T), 2 as $T);
773 assert_eq!(( 3 as $T).wrapped(3 as $T), 0 as $T);
774 assert_eq!(( 4 as $T).wrapped(3 as $T), 1 as $T);
775 assert_eq!(( 5 as $T).wrapped(3 as $T), 2 as $T);
776 }
777 #[test]
778 fn wrapped_between() {
779 assert_eq!((-4 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
780 assert_eq!((-3 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
781 assert_eq!((-2 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
782 assert_eq!((-1 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
783 assert_eq!(( 0 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
784 assert_eq!(( 1 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
785 assert_eq!(( 2 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
786 assert_eq!(( 3 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
787 assert_eq!(( 4 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
788 assert_eq!(( 5 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
789 assert_eq!(( 6 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
790 }
791 #[test]
792 fn pingpong() {
793 assert_eq!((-4 as $T).pingpong(3 as $T), 2 as $T);
794 assert_eq!((-3 as $T).pingpong(3 as $T), 3 as $T);
795 assert_eq!((-2 as $T).pingpong(3 as $T), 2 as $T);
796 assert_eq!((-1 as $T).pingpong(3 as $T), 1 as $T);
797 assert_eq!(( 0 as $T).pingpong(3 as $T), 0 as $T);
798 assert_eq!(( 1 as $T).pingpong(3 as $T), 1 as $T);
799 assert_eq!(( 2 as $T).pingpong(3 as $T), 2 as $T);
800 assert_eq!(( 3 as $T).pingpong(3 as $T), 3 as $T);
801 assert_eq!(( 4 as $T).pingpong(3 as $T), 2 as $T);
802 assert_eq!(( 5 as $T).pingpong(3 as $T), 1 as $T);
803 assert_eq!(( 6 as $T).pingpong(3 as $T), 0 as $T);
804 assert_eq!(( 7 as $T).pingpong(3 as $T), 1 as $T);
805 }
806 })+
807 };
808 }
809
810 macro_rules! for_each_float_type {
811 ($($T:ident)+) => {
812 $(mod $T {
813 use super::Wrap;
814 #[test]
815 fn wrapped() {
816 assert_relative_eq!((-5 as $T).wrapped(3 as $T), 1 as $T);
817 assert_relative_eq!((-4 as $T).wrapped(3 as $T), 2 as $T);
818 assert_relative_eq!((-3 as $T).wrapped(3 as $T), 0 as $T);
819 assert_relative_eq!((-2 as $T).wrapped(3 as $T), 1 as $T);
820 assert_relative_eq!((-1 as $T).wrapped(3 as $T), 2 as $T);
821 assert_relative_eq!(( 0 as $T).wrapped(3 as $T), 0 as $T);
822 assert_relative_eq!(( 1 as $T).wrapped(3 as $T), 1 as $T);
823 assert_relative_eq!(( 2 as $T).wrapped(3 as $T), 2 as $T);
824 assert_relative_eq!(( 3 as $T).wrapped(3 as $T), 0 as $T);
825 assert_relative_eq!(( 4 as $T).wrapped(3 as $T), 1 as $T);
826 assert_relative_eq!(( 5 as $T).wrapped(3 as $T), 2 as $T);
827 }
828 #[test]
829 fn wrapped_between() {
830 assert_relative_eq!((-4 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
831 assert_relative_eq!((-3 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
832 assert_relative_eq!((-2 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
833 assert_relative_eq!((-1 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
834 assert_relative_eq!(( 0 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
835 assert_relative_eq!(( 1 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
836 assert_relative_eq!(( 2 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
837 assert_relative_eq!(( 3 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
838 assert_relative_eq!(( 4 as $T).wrapped_between(2 as $T, 5 as $T), 4 as $T);
839 assert_relative_eq!(( 5 as $T).wrapped_between(2 as $T, 5 as $T), 2 as $T);
840 assert_relative_eq!(( 6 as $T).wrapped_between(2 as $T, 5 as $T), 3 as $T);
841 }
842 #[test]
843 fn pingpong() {
844 assert_relative_eq!((-4 as $T).pingpong(3 as $T), 2 as $T);
845 assert_relative_eq!((-3 as $T).pingpong(3 as $T), 3 as $T);
846 assert_relative_eq!((-2 as $T).pingpong(3 as $T), 2 as $T);
847 assert_relative_eq!((-1 as $T).pingpong(3 as $T), 1 as $T);
848 assert_relative_eq!(( 0 as $T).pingpong(3 as $T), 0 as $T);
849 assert_relative_eq!(( 1 as $T).pingpong(3 as $T), 1 as $T);
850 assert_relative_eq!(( 2 as $T).pingpong(3 as $T), 2 as $T);
851 assert_relative_eq!(( 3 as $T).pingpong(3 as $T), 3 as $T);
852 assert_relative_eq!(( 4 as $T).pingpong(3 as $T), 2 as $T);
853 assert_relative_eq!(( 5 as $T).pingpong(3 as $T), 1 as $T);
854 assert_relative_eq!(( 6 as $T).pingpong(3 as $T), 0 as $T);
855 assert_relative_eq!(( 7 as $T).pingpong(3 as $T), 1 as $T);
856 }
857 })+
858 };
859 }
860
861 for_each_float_type!{f32 f64}
862 for_each_signed_type!{i8 i16 i32 i64 isize}
863 for_each_unsigned_type!{u8 u16 u32 u64 usize}
864}