pub mod nofailure;
pub mod error;
pub(crate) mod util;
use core::ops::{Add, Div, Mul, Neg, Sub};
use error::{Error, ErrorTime};
use num_traits::{ConstOne, Float, Zero};
use util::*;
#[inline]
pub fn height_from_time_and_impulse<N>(time: N, impulse: N) -> Result<N, Error>
where
N: ConstOne + Add<Output = N> + Mul<Output = N> + Div<Output = N>,
{
Ok(nofailure::height_from_time_and_impulse(time, impulse))
}
#[inline]
pub fn height_from_time_and_gravity<N>(time: N, gravity: N) -> Result<N, Error>
where
N: Copy + ConstOne + Neg<Output = N> + Add<Output = N> + Mul<Output = N> + Div<Output = N>,
{
Ok(nofailure::height_from_time_and_gravity(time, gravity))
}
#[inline]
pub fn height_from_impulse_and_gravity<N>(impulse: N, gravity: N) -> Result<N, Error>
where
N: Copy
+ Zero
+ ConstOne
+ Neg<Output = N>
+ Add<Output = N>
+ Mul<Output = N>
+ Div<Output = N>,
{
if gravity.is_zero() {
Err(Error::Gravity)
} else {
Ok(-halve(pow2(impulse)) / gravity)
}
}
#[inline]
pub fn time_from_height_and_impulse<N>(height: N, impulse: N) -> Result<N, Error>
where
N: Copy + Zero + Add<Output = N> + Div<Output = N>,
{
if impulse.is_zero() {
Err(Error::Impulse)
} else {
Ok(double(height) / impulse)
}
}
#[inline]
pub fn time_from_height_and_gravity<N>(height: N, gravity: N) -> Result<N, Error>
where
N: Zero + Float + Div<Output = N>,
{
if gravity.is_zero() {
Err(Error::Gravity)
} else {
Ok((double(height) / gravity).abs().sqrt())
}
}
#[inline]
pub fn time_from_impulse_and_gravity<N>(impulse: N, gravity: N) -> Result<N, Error>
where
N: Zero + Neg<Output = N> + Div<Output = N>,
{
if gravity.is_zero() {
Err(Error::Gravity)
} else {
Ok(-impulse / gravity)
}
}
#[inline]
pub fn impulse_from_height_and_time<N>(height: N, time: N) -> Result<N, Error>
where
N: Copy + Zero + Add<Output = N> + Div<Output = N>,
{
if time.is_zero() {
Err(Error::Time)
} else {
Ok(double(height) / time)
}
}
#[inline]
pub fn impulse_from_height_and_gravity<N>(height: N, gravity: N) -> Result<N, Error>
where
N: Float,
{
Ok(nofailure::impulse_from_height_and_gravity(height, gravity))
}
#[inline]
pub fn impulse_from_time_and_gravity<N>(time: N, gravity: N) -> Result<N, Error>
where
N: Neg<Output = N> + Mul<Output = N>,
{
Ok(nofailure::impulse_from_time_and_gravity(time, gravity))
}
#[inline]
pub fn gravity_from_height_and_time<N>(height: N, time: N) -> Result<N, Error>
where
N: Copy + Zero + Neg<Output = N> + Add<Output = N> + Mul<Output = N> + Div<Output = N>,
{
if time.is_zero() {
Err(Error::Time)
} else {
Ok(-double(height) / pow2(time))
}
}
#[inline]
pub fn gravity_from_height_and_impulse<N>(height: N, impulse: N) -> Result<N, Error>
where
N: Copy
+ Zero
+ ConstOne
+ Neg<Output = N>
+ Add<Output = N>
+ Mul<Output = N>
+ Div<Output = N>,
{
if height.is_zero() {
Err(Error::Height)
} else {
Ok(-halve(pow2(impulse)) / height)
}
}
#[inline]
pub fn gravity_from_time_and_impulse<N>(time: N, impulse: N) -> Result<N, Error>
where
N: Zero + Neg<Output = N> + Div<Output = N>,
{
if time.is_zero() {
Err(Error::Time)
} else {
Ok(-impulse / time)
}
}
#[inline]
pub fn time_from_speed_and_range<N>(speed: N, range: N) -> Result<N, ErrorTime>
where
N: Zero + ConstOne + Add<Output = N> + Div<Output = N> + Div<Output = N>,
{
if speed.is_zero() {
Err(ErrorTime::Speed)
} else {
Ok(halve(range) / speed)
}
}
#[inline]
pub fn time_from_speed_and_range_with_ratio<N>(
speed: N,
range: N,
ratio: N,
) -> Result<(N, N), ErrorTime>
where
N: Copy
+ Zero
+ ConstOne
+ Add<Output = N>
+ Sub<Output = N>
+ Div<Output = N>
+ Div<Output = N>,
{
if speed.is_zero() {
Err(ErrorTime::Speed)
} else {
let time = halve(range) / speed;
Ok((time * ratio, time * (N::ONE - ratio)))
}
}
#[cfg(test)]
mod tests {
#[test]
fn test_jump_parameter() {
use super::*;
const HEIGHT: f32 = 20.0;
const TIME: f32 = 10.0;
let impulse = impulse_from_height_and_time::<f32>(HEIGHT, TIME).unwrap();
let gravity: f32 = gravity_from_height_and_time(HEIGHT, TIME).unwrap();
let time2: f32 = time_from_height_and_gravity(20.0, gravity).unwrap();
assert_eq!(impulse, 4.0);
assert_eq!(gravity, -0.4);
assert_eq!(time2, 10.0);
}
}