Fully impl operator permutations, and remove Zero and One impls
This commit is contained in:
parent
8f60f0a666
commit
369c1202c3
1 changed files with 80 additions and 137 deletions
217
src/angle.rs
217
src/angle.rs
|
@ -22,7 +22,7 @@ use std::ops::*;
|
||||||
use rand::{Rand, Rng};
|
use rand::{Rand, Rng};
|
||||||
use rand::distributions::range::SampleRange;
|
use rand::distributions::range::SampleRange;
|
||||||
|
|
||||||
use rust_num::{Float, One, Zero};
|
use rust_num::{Float, Zero};
|
||||||
use rust_num::traits::cast;
|
use rust_num::traits::cast;
|
||||||
|
|
||||||
use approx::ApproxEq;
|
use approx::ApproxEq;
|
||||||
|
@ -75,7 +75,7 @@ impl<S: BaseFloat> ScalarConv<S> for Deg<S> {
|
||||||
|
|
||||||
/// Operations on angles.
|
/// Operations on angles.
|
||||||
pub trait Angle where
|
pub trait Angle where
|
||||||
Self: Clone + Zero,
|
Self: Copy + Clone,
|
||||||
Self: PartialEq + PartialOrd,
|
Self: PartialEq + PartialOrd,
|
||||||
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
|
// FIXME: Ugly type signatures - blocked by rust-lang/rust#24092
|
||||||
Self: ApproxEq<Epsilon = <Self as Angle>::Unitless>,
|
Self: ApproxEq<Epsilon = <Self as Angle>::Unitless>,
|
||||||
|
@ -91,7 +91,7 @@ pub trait Angle where
|
||||||
fn from<A: Angle<Unitless = Self::Unitless>>(theta: A) -> Self;
|
fn from<A: Angle<Unitless = Self::Unitless>>(theta: A) -> Self;
|
||||||
|
|
||||||
/// Negate this angle, in-place.
|
/// Negate this angle, in-place.
|
||||||
#[inline] fn neg_self(&mut self) { *self = -(*self).clone() }
|
#[inline] fn neg_self(&mut self) { *self = -*self }
|
||||||
|
|
||||||
/// Add this angle with another, returning the new angle.
|
/// Add this angle with another, returning the new angle.
|
||||||
#[inline] fn add_a(&self, other: Self) -> Self { ScalarConv::from(*self.s() + *other.s()) }
|
#[inline] fn add_a(&self, other: Self) -> Self { ScalarConv::from(*self.s() + *other.s()) }
|
||||||
|
@ -149,6 +149,7 @@ pub trait Angle where
|
||||||
self.add_a(self.sub_a(other).mul_s(cast(0.5f64).unwrap())).normalize()
|
self.add_a(self.sub_a(other).mul_s(cast(0.5f64).unwrap())).normalize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn zero() -> Self;
|
||||||
fn full_turn() -> Self;
|
fn full_turn() -> Self;
|
||||||
|
|
||||||
#[inline] fn turn_div_2() -> Self { Self::full_turn().div_s(cast(2i8).unwrap()) }
|
#[inline] fn turn_div_2() -> Self { Self::full_turn().div_s(cast(2i8).unwrap()) }
|
||||||
|
@ -161,97 +162,6 @@ pub trait Angle where
|
||||||
|
|
||||||
#[inline] pub fn bisect<A: Angle>(a: A, b: A) -> A { a.bisect(b) }
|
#[inline] pub fn bisect<A: Angle>(a: A, b: A) -> A { a.bisect(b) }
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Add<R> for Rad<S> {
|
|
||||||
type Output = Rad<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn add(self, other: R) -> Rad<S> { rad(self.s + other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Add<R> for Deg<S> {
|
|
||||||
type Output = Deg<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn add(self, other: R) -> Deg<S> { deg(self.s + other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Sub<R> for Rad<S> {
|
|
||||||
type Output = Rad<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn sub(self, other: R) -> Rad<S> { rad(self.s - other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Sub<R> for Deg<S> {
|
|
||||||
type Output = Deg<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn sub(self, other: R) -> Deg<S> { deg(self.s - other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> Neg for Rad<S> {
|
|
||||||
type Output = Rad<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn neg(self) -> Rad<S> { rad(-self.s) }
|
|
||||||
}
|
|
||||||
impl<S: BaseFloat> Neg for Deg<S> {
|
|
||||||
type Output = Deg<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn neg(self) -> Deg<S> { deg(-self.s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> Zero for Rad<S> {
|
|
||||||
#[inline]
|
|
||||||
fn zero() -> Rad<S> { rad(S::zero()) }
|
|
||||||
#[inline]
|
|
||||||
fn is_zero(&self) -> bool { *self == Self::zero() }
|
|
||||||
}
|
|
||||||
impl<S: BaseFloat> Zero for Deg<S> {
|
|
||||||
#[inline]
|
|
||||||
fn zero() -> Deg<S> { deg(S::zero()) }
|
|
||||||
#[inline]
|
|
||||||
fn is_zero(&self) -> bool { *self == Self::zero() }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Mul<R> for Rad<S> {
|
|
||||||
type Output = Rad<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, other: R) -> Rad<S> { rad(self.s * other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Into<Rad<S>>, S: BaseFloat> Mul<R> for Deg<S> {
|
|
||||||
type Output = Deg<S>;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn mul(self, other: R) -> Deg<S> { deg(self.s * other.into().s) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> One for Rad<S> {
|
|
||||||
#[inline]
|
|
||||||
fn one() -> Rad<S> { rad(S::one()) }
|
|
||||||
}
|
|
||||||
impl<S: BaseFloat> One for Deg<S> {
|
|
||||||
#[inline]
|
|
||||||
fn one() -> Deg<S> { deg(S::one()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
const PI_2: f64 = f64::consts::PI * 2f64;
|
|
||||||
|
|
||||||
impl<S: BaseFloat> Angle for Rad<S> {
|
|
||||||
type Unitless = S;
|
|
||||||
#[inline] fn from<A: Angle<Unitless = S>>(theta: A) -> Rad<S> { theta.into() }
|
|
||||||
#[inline] fn full_turn() -> Rad<S> { rad(cast(PI_2).unwrap()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> Angle for Deg<S> {
|
|
||||||
type Unitless = S;
|
|
||||||
#[inline] fn from<A: Angle<Unitless = S>>(theta: A) -> Deg<S> { theta.into() }
|
|
||||||
#[inline] fn full_turn() -> Deg<S> { deg(cast(360i32).unwrap()) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline] pub fn sin<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.sin() }
|
#[inline] pub fn sin<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.sin() }
|
||||||
#[inline] pub fn cos<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.cos() }
|
#[inline] pub fn cos<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.cos() }
|
||||||
#[inline] pub fn tan<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.tan() }
|
#[inline] pub fn tan<S: BaseFloat, R: Into<Rad<S>>>(theta: R) -> S { theta.into().s.tan() }
|
||||||
|
@ -266,49 +176,82 @@ impl<S: BaseFloat> Angle for Deg<S> {
|
||||||
#[inline] pub fn atan<S: BaseFloat, R: From<Rad<S>>>(s: S) -> R { rad(s.atan()).into() }
|
#[inline] pub fn atan<S: BaseFloat, R: From<Rad<S>>>(s: S) -> R { rad(s.atan()).into() }
|
||||||
#[inline] pub fn atan2<S: BaseFloat, R: From<Rad<S>>>(a: S, b: S) -> R { rad(a.atan2(b)).into() }
|
#[inline] pub fn atan2<S: BaseFloat, R: From<Rad<S>>>(a: S, b: S) -> R { rad(a.atan2(b)).into() }
|
||||||
|
|
||||||
impl<S: BaseFloat + fmt::Debug> fmt::Debug for Rad<S> {
|
macro_rules! impl_angle {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
($Angle:ident, $fmt:expr, $full_turn:expr, $hi:expr) => {
|
||||||
write!(f, "{:?} rad", self.s)
|
impl<S: BaseFloat> Angle for $Angle<S> {
|
||||||
|
type Unitless = S;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn zero() -> $Angle<S> { ScalarConv::from(S::zero()) }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn from<A: Angle<Unitless = S>>(theta: A) -> $Angle<S> { theta.into() }
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn full_turn() -> $Angle<S> { ScalarConv::from(cast($full_turn).unwrap()) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat> Neg for $Angle<S> {
|
||||||
|
type Output = $Angle<S>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn neg(self) -> $Angle<S> { ScalarConv::from(-self.s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: BaseFloat> Neg for &'a $Angle<S> {
|
||||||
|
type Output = $Angle<S>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn neg(self) -> $Angle<S> { ScalarConv::from(-self.s) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Add<$Angle<S> > for $Angle<S> {
|
||||||
|
fn add(lhs, rhs) -> $Angle<S> { ScalarConv::from(lhs.s + rhs.s) }
|
||||||
|
});
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Sub<$Angle<S> > for $Angle<S> {
|
||||||
|
fn sub(lhs, rhs) -> $Angle<S> { ScalarConv::from(lhs.s - rhs.s) }
|
||||||
|
});
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Div<$Angle<S> > for $Angle<S> {
|
||||||
|
fn div(lhs, rhs) -> S { lhs.s / rhs.s }
|
||||||
|
});
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Rem<$Angle<S> > for $Angle<S> {
|
||||||
|
fn rem(lhs, rhs) -> S { lhs.s % rhs.s }
|
||||||
|
});
|
||||||
|
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Mul<S> for $Angle<S> {
|
||||||
|
fn mul(lhs, scalar) -> $Angle<S> { ScalarConv::from(lhs.s * scalar) }
|
||||||
|
});
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Div<S> for $Angle<S> {
|
||||||
|
fn div(lhs, scalar) -> $Angle<S> { ScalarConv::from(lhs.s / scalar) }
|
||||||
|
});
|
||||||
|
impl_binary_operator!(<S: BaseFloat> Rem<S> for $Angle<S> {
|
||||||
|
fn rem(lhs, scalar) -> $Angle<S> { ScalarConv::from(lhs.s % scalar) }
|
||||||
|
});
|
||||||
|
|
||||||
|
impl<S: BaseFloat> ApproxEq for $Angle<S> {
|
||||||
|
type Epsilon = S;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn approx_eq_eps(&self, other: &$Angle<S>, epsilon: &S) -> bool {
|
||||||
|
self.s.approx_eq_eps(&other.s, epsilon)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat + SampleRange> Rand for $Angle<S> {
|
||||||
|
#[inline]
|
||||||
|
fn rand<R: Rng>(rng: &mut R) -> $Angle<S> {
|
||||||
|
let angle: S = rng.gen_range(cast(-$hi).unwrap(), cast($hi).unwrap());
|
||||||
|
ScalarConv::from(angle)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: BaseFloat> fmt::Debug for $Angle<S> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
write!(f, $fmt, self.s)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: BaseFloat + fmt::Debug>
|
impl_angle!(Rad, "{:?} rad", f64::consts::PI * 2.0, f64::consts::PI);
|
||||||
fmt::Debug for Deg<S> {
|
impl_angle!(Deg, "{:?}°", 360, 180);
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "{:?}°", self.s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> ApproxEq for Rad<S> {
|
|
||||||
type Epsilon = S;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn approx_eq_eps(&self, other: &Rad<S>, epsilon: &S) -> bool {
|
|
||||||
self.s.approx_eq_eps(&other.s, epsilon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat> ApproxEq for Deg<S> {
|
|
||||||
type Epsilon = S;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn approx_eq_eps(&self, other: &Deg<S>, epsilon: &S) -> bool {
|
|
||||||
self.s.approx_eq_eps(&other.s, epsilon)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat + PartialOrd + SampleRange + Rand> Rand for Rad<S> {
|
|
||||||
#[inline]
|
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Rad<S> {
|
|
||||||
let angle: S = rng.gen_range(cast(-f64::consts::PI).unwrap(), cast(f64::consts::PI).unwrap());
|
|
||||||
rad(angle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: BaseFloat + PartialOrd + SampleRange + Rand> Rand for Deg<S> {
|
|
||||||
#[inline]
|
|
||||||
fn rand<R: Rng>(rng: &mut R) -> Deg<S> {
|
|
||||||
let angle: S = rng.gen_range(cast(-180f64).unwrap(), cast(180f64).unwrap());
|
|
||||||
deg(angle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in a new issue