use std::ops::Range;
pub fn nearly_eq<S, T>(x: S, y: T) -> bool
where
S: Into<f64>,
T: Into<f64>,
{
let mut b: bool = false;
let e = 1e-7;
let p: f64 = x.into().abs();
let q: f64 = y.into().abs();
if (p - q).abs() < e || (p - q).abs() / (p + q).min(f64::MAX) < e {
b = true;
}
b
}
#[allow(unused_comparisons)]
pub fn tab(s: &str, space: usize) -> String {
let l = s.len();
let mut m: String = String::new();
let fs = format!("{}{}", " ".repeat(space - l), s);
m.push_str(&fs);
m
}
pub fn quot_rem(x: usize, y: usize) -> (i32, i32) {
((x / y) as i32, (x % y) as i32)
}
pub fn choose_shorter_string(x1: String, x2: String) -> String {
if x1.len() > x2.len() {
x2
} else {
x1
}
}
pub fn choose_shorter_vec(x1: &[f64], x2: &[f64]) -> Vec<f64> {
if x1.len() > x2.len() {
x2.to_vec()
} else {
x1.to_vec()
}
}
pub fn choose_longer_vec(x1: &[f64], x2: &[f64]) -> Vec<f64> {
if x1.len() <= x2.len() {
x2.to_vec()
} else {
x1.to_vec()
}
}
pub fn max<T>(v: Vec<T>) -> T
where
T: PartialOrd + Copy + Clone,
{
let l = v.len();
if l == 1 {
v[0]
} else {
let mut t = if v[0] >= v[1] { v[0] } else { v[1] };
for &x in v.iter().skip(2) {
if x > t {
t = x;
}
}
t
}
}
pub fn min<T>(v: Vec<T>) -> T
where
T: PartialOrd + Copy + Clone,
{
let l = v.len();
if l == 1 {
v[0]
} else {
let mut t = if v[0] <= v[1] { v[0] } else { v[1] };
for &x in v.iter().skip(2) {
if x < t {
t = x;
}
}
t
}
}
pub fn sgn(x: usize) -> f64 {
if x.is_multiple_of(2) {
1f64
} else {
-1f64
}
}
pub fn eq_vec(x: &[f64], y: &[f64], tol: f64) -> bool {
x.iter().zip(y.iter()).all(|(x, y)| (x - y).abs() <= tol)
}
pub fn auto_zip<T: Clone>(x: &[T]) -> Vec<(T, T)> {
let x_head = x[0..x.len() - 1].to_vec();
let x_tail = x[1..x.len()].to_vec();
x_head.into_iter().zip(x_tail).collect()
}
pub fn find_interval<T: PartialOrd + PartialEq>(sorted_intervals: &[(T, T)], x: T) -> usize {
let mut i = 0;
let mut j = sorted_intervals.len() - 1;
assert!(
x >= sorted_intervals[0].0,
"x is smaller than the smallest interval"
);
assert!(
x <= sorted_intervals[sorted_intervals.len() - 1].1,
"x is larger than the largest interval"
);
while i <= j {
let mid = (i + j) / 2;
if x < sorted_intervals[mid].0 {
j = mid - 1;
} else if x > sorted_intervals[mid].1 {
i = mid + 1;
} else {
return mid;
}
}
i
}
pub fn gen_range<T: Clone + PartialOrd>(x: &[T]) -> Vec<Range<T>> {
let mut r = Vec::new();
for i in 0..x.len() - 1 {
r.push(Range {
start: x[i].clone(),
end: x[i + 1].clone(),
});
}
r
}
pub fn zip_range<T: Clone + PartialOrd, U: Clone>(x: &[T], y: &[U]) -> Vec<(Range<T>, U)> {
y[0..x.len() - 1]
.iter()
.enumerate()
.map(|(i, yi)| {
(
Range {
start: x[i].clone(),
end: x[i + 1].clone(),
},
yi.clone(),
)
})
.collect()
}