use num_traits::{Float, Num};
pub fn pi<T: Float>() -> T {
T::from(3.141592653589).unwrap()
}
pub fn tau<T: Float>() -> T {
T::from(2.0).unwrap() * pi()
}
pub fn phi<T: Float>() -> T {
T::from(1.618033988).unwrap()
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Angle<T: Float> {
Deg(T),
Rad(T),
}
impl<T: Float> Angle<T> {
pub fn degrees(self) -> T {
match self {
Self::Deg(d) => d,
Self::Rad(r) => r.to_degrees(),
}
}
pub fn radians(self) -> T {
match self {
Self::Deg(d) => d.to_radians(),
Self::Rad(r) => r,
}
}
pub fn add(&mut self, x: T) {
match self {
Self::Deg(n) => *n = (*n + x) % Self::degrees_360().degrees(),
Self::Rad(n) => *n = (*n + x) % Self::full_radians().radians(),
}
}
pub fn sub(&mut self, x: T) {
self.add(-x);
}
pub fn half_radians() -> Self {
Self::Rad(pi())
}
pub fn full_radians() -> Self {
Self::Rad(tau())
}
pub fn degrees_180() -> Self {
Self::Deg(T::from(180.0).unwrap())
}
pub fn degrees_360() -> Self {
Self::Deg(T::from(360.0).unwrap())
}
}
pub use Angle::{Deg, Rad};
pub fn lerp<T: Clone + Float>(a: T, b: T, t: T) -> T {
(T::one() - t) * a + t * b
}
pub fn fact<T: Clone + Num + PartialOrd>(n: T) -> T {
let mut x = n.clone();
let mut accum = T::one();
loop {
accum = x.clone() * accum.clone();
x = x - T::one();
if x <= T::one() {
break accum;
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn angle() {
let d90 = Deg(90.0);
let rad = Rad(d90.radians());
assert_eq!(d90.radians(), rad.radians());
let mut x = Deg(346.68);
x.add(43.59);
println!("{}", x.degrees());
let mut y = Rad(pi::<f64>());
y.add(2.0 * pi::<f64>());
println!("{}", y.radians()); }
#[test]
fn lerp() {
for i in [0.00, 0.25, 0.50, 0.75, 1.00] {
let x = match i {
0.00 => 0.0,
0.25 => 50.0,
0.50 => 100.0,
0.75 => 150.0,
1.00 => 200.0,
_ => unreachable!(),
};
assert_eq!(x, super::lerp(0.0, 200.0, i));
}
}
#[test]
fn fact() {
assert_eq!(0, super::fact(0));
assert_eq!(1, super::fact(1));
assert_eq!(24, super::fact(4));
assert_eq!(120, super::fact(5));
assert_eq!(720, super::fact(6));
}
#[test]
fn constants() {
let pif32 = pi::<f32>();
println!("pi f32: {pif32}");
let pif64 = pi::<f64>();
println!("pi f64: {pif64}");
let tauf32 = tau::<f32>();
println!("2pi f32: {tauf32}");
let phif32 = phi::<f32>();
println!("phi f32: {phif32}");
}
}