pub trait Wrap<Bound = Self>: Sized {
// Required methods
fn wrapped(self, upper: Bound) -> Self;
fn wrapped_between(self, lower: Bound, upper: Bound) -> Self;
fn pingpong(self, upper: Bound) -> Self;
// Provided methods
fn wrap(val: Self, upper: Bound) -> Self { ... }
fn wrapped_2pi(self) -> Self
where Bound: FloatConst + Add<Output = Bound> { ... }
fn wrap_2pi(val: Self) -> Self
where Bound: FloatConst + Add<Output = Bound> { ... }
fn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
where Self: Sub<Output = Self> + Add<Output = Self> + From<Bound>,
Bound: Copy + Sub<Output = Bound> + PartialOrd { ... }
fn delta_angle(self, target: Self) -> Self
where Self: From<Bound> + Sub<Output = Self> + PartialOrd,
Bound: FloatConst + Add<Output = Bound> { ... }
fn delta_angle_degrees(self, target: Self) -> Self
where Self: From<Bound> + Sub<Output = Self> + PartialOrd,
Bound: From<u16> { ... }
}Expand description
A value that can wrap itself around given bounds.
Required Methods§
Sourcefn wrapped(self, upper: Bound) -> Self
fn wrapped(self, upper: Bound) -> Self
Returns this value, wrapped between zero and some upper bound (both inclusive).
The computation is self - (self/upper).floor() * upper.
This might look like the remainder (%) operator, but behaves differently with negative
values.
If you’re familiar with Unity, this is the Mathf.Repeat() function.
§Panics
Panics if upper <= 0. Reasons include :
- Some types may implement it as
self.wrapped_between(zero, upper). A negativeupperwould violate thelower <= upperrequirement in this case; - On unsigned integers, this just resolves to
self % upper, and integer division by zero is forbidden. Testing fori==0incurs unnecessary overhead. - Handling negative
uppervalues would double the number of test cases and increases implementation complexity;
use vek::ops::Wrap;
assert_eq!((-5_i32).wrapped(3), 1);
assert_eq!((-4_i32).wrapped(3), 2);
assert_eq!((-3_i32).wrapped(3), 0);
assert_eq!((-2_i32).wrapped(3), 1);
assert_eq!((-1_i32).wrapped(3), 2);
assert_eq!(0_i32.wrapped(3), 0);
assert_eq!(1_i32.wrapped(3), 1);
assert_eq!(2_i32.wrapped(3), 2);
assert_eq!(3_i32.wrapped(3), 0);
assert_eq!(4_i32.wrapped(3), 1);
assert_eq!(5_i32.wrapped(3), 2);Sourcefn wrapped_between(self, lower: Bound, upper: Bound) -> Self
fn wrapped_between(self, lower: Bound, upper: Bound) -> Self
Returns this value, wrapped between lower (inclusive) and upper (exclusive).
§Panics
Panics if lower >= upper. Swap the values yourself if necessary.
Also panics if lower < 0 or upper <= 0. See wrapped() for a rationale.
Forcing lower and upper to be positive allows implementations to be simpler and faster.
use vek::ops::Wrap;
assert_eq!((-4_i32).wrapped_between(2, 5), 2);
assert_eq!((-3_i32).wrapped_between(2, 5), 3);
assert_eq!((-2_i32).wrapped_between(2, 5), 4);
assert_eq!((-1_i32).wrapped_between(2, 5), 2);
assert_eq!( 0_i32 .wrapped_between(2, 5), 3);
assert_eq!( 1_i32 .wrapped_between(2, 5), 4);
assert_eq!( 2_i32 .wrapped_between(2, 5), 2);
assert_eq!( 3_i32 .wrapped_between(2, 5), 3);
assert_eq!( 4_i32 .wrapped_between(2, 5), 4);
assert_eq!( 5_i32 .wrapped_between(2, 5), 2);
assert_eq!( 6_i32 .wrapped_between(2, 5), 3);Sourcefn pingpong(self, upper: Bound) -> Self
fn pingpong(self, upper: Bound) -> Self
Wraps a value such that it goes back and forth from zero to upper (inclusive) as it increases.
§Panics
Panics if upper <= 0. See wrapped() for a rationale.
use vek::ops::Wrap;
assert_eq!((-4_i32).pingpong(3), 2);
assert_eq!((-3_i32).pingpong(3), 3);
assert_eq!((-2_i32).pingpong(3), 2);
assert_eq!((-1_i32).pingpong(3), 1);
assert_eq!( 0_i32 .pingpong(3), 0);
assert_eq!( 1_i32 .pingpong(3), 1);
assert_eq!( 2_i32 .pingpong(3), 2);
assert_eq!( 3_i32 .pingpong(3), 3);
assert_eq!( 4_i32 .pingpong(3), 2);
assert_eq!( 5_i32 .pingpong(3), 1);
assert_eq!( 6_i32 .pingpong(3), 0);
assert_eq!( 7_i32 .pingpong(3), 1);Provided Methods§
Sourcefn wrap(val: Self, upper: Bound) -> Self
fn wrap(val: Self, upper: Bound) -> Self
Alias to wrapped() which doesn’t take self.
§Panics
Panics if upper <= 0. See wrapped() for a rationale.
Sourcefn wrapped_2pi(self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
fn wrapped_2pi(self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
Returns this value, wrapped between zero and two times 𝛑 (inclusive).
This ought to be named wrapped_tau, but I assume people are
more familiar with 𝛑, and 2pi is therefore more evocative.
Sourcefn wrap_2pi(val: Self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
fn wrap_2pi(val: Self) -> Selfwhere
Bound: FloatConst + Add<Output = Bound>,
Alias to wrapped_2pi which doesn’t take self.
This ought to be named wrap_tau, but I assume people are
more familiar with 𝛑, and 2pi is therefore more evocative.
Sourcefn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
fn wrap_between(val: Self, lower: Bound, upper: Bound) -> Self
Alias to wrapped_between which doesn’t take self.
§Panics
Panics if lower is greater than upper. Swap the values yourself if necessary.
Sourcefn delta_angle(self, target: Self) -> Self
fn delta_angle(self, target: Self) -> Self
Calculates the shortest difference between two given angles, in radians.
Sourcefn delta_angle_degrees(self, target: Self) -> Self
fn delta_angle_degrees(self, target: Self) -> Self
Calculates the shortest difference between two given angles, in degrees.
This exists because it’s enough for Bound to implement From<u16>.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.