use crate::result::{Failure, Result};
use num::{Num, NumCast};
use rand::{thread_rng, Rng};
use std::iter::Sum;
pub fn assert(pred: bool, failure: Failure) -> Result<()> {
if pred {
Ok(())
} else {
Err(failure)
}
}
pub fn frac(x: f64) -> f64 {
x - x.floor()
}
pub fn max<T>(x: T, y: T) -> T
where
T: PartialOrd,
{
if x > y {
x
} else {
y
}
}
pub fn min<T>(x: T, y: T) -> T
where
T: PartialOrd,
{
if x > y {
y
} else {
x
}
}
pub fn pos<T>(x: T) -> T
where
T: NumCast + PartialOrd,
{
max(NumCast::from(0).unwrap(), x)
}
pub fn project<T>(x: T, a: T, b: T) -> T
where
T: PartialOrd,
{
max(a, min(b, x))
}
pub fn is_pow_of_2(x: i32) -> bool {
x != 0 && x & (x - 1) == 0
}
pub fn access<T>(xs: &Vec<T>, i: i32) -> Option<&T> {
if 1 <= i && i <= xs.len() as i32 {
Some(&xs[i as usize - 1])
} else {
None
}
}
pub fn sample_uniform(a: f64, b: f64) -> f64 {
let mut rng = thread_rng();
rng.gen_range(a..=b)
}
pub fn shift_time(t: i32, t_start: i32) -> i32 {
t + t_start - 1
}
pub fn unshift_time(t: i32, t_start: i32) -> i32 {
t - t_start + 1
}
pub fn mean<T>(xs: Vec<T>) -> T
where
T: Copy + Num + NumCast + Sum,
{
assert!(!xs.is_empty());
let n = NumCast::from(xs.len()).unwrap();
xs.into_iter().sum::<T>() / n
}