peroxide/util/
useful.rs

1//! Useful missing tools
2
3use std::ops::Range;
4
5// =============================================================================
6// Fundamental Utils
7// =============================================================================
8
9/// Near equal
10///
11/// # Examples
12/// ```
13/// extern crate peroxide;
14/// use peroxide::fuga::*;
15///
16/// assert!(nearly_eq(1.0/3.0 * 3.0, 1));
17/// ```
18pub fn nearly_eq<S, T>(x: S, y: T) -> bool
19where
20    S: Into<f64>,
21    T: Into<f64>,
22{
23    let mut b: bool = false;
24    let e = 1e-7;
25    let p: f64 = x.into().abs();
26    let q: f64 = y.into().abs();
27    if (p - q).abs() < e || (p - q).abs() / (p + q).min(f64::MAX) < e {
28        b = true;
29    }
30    b
31}
32
33#[allow(unused_comparisons)]
34pub fn tab(s: &str, space: usize) -> String {
35    let l = s.len();
36    let mut m: String = String::new();
37    let fs = format!("{}{}", " ".repeat(space - l), s);
38    m.push_str(&fs);
39    m
40}
41
42pub fn quot_rem(x: usize, y: usize) -> (i32, i32) {
43    ((x / y) as i32, (x % y) as i32)
44}
45
46// =============================================================================
47// Choose Utils
48// =============================================================================
49pub fn choose_shorter_string(x1: String, x2: String) -> String {
50    if x1.len() > x2.len() {
51        x2
52    } else {
53        x1
54    }
55}
56
57pub fn choose_shorter_vec(x1: &Vec<f64>, x2: &Vec<f64>) -> Vec<f64> {
58    if x1.len() > x2.len() {
59        x2.clone()
60    } else {
61        x1.clone()
62    }
63}
64
65pub fn choose_longer_vec(x1: &Vec<f64>, x2: &Vec<f64>) -> Vec<f64> {
66    if x1.len() <= x2.len() {
67        x2.clone()
68    } else {
69        x1.clone()
70    }
71}
72
73pub fn max<T>(v: Vec<T>) -> T
74where
75    T: PartialOrd + Copy + Clone,
76{
77    let l = v.len();
78    if l == 1 {
79        v[0]
80    } else {
81        let mut t = if v[0] >= v[1] { v[0] } else { v[1] };
82        for i in 2..v.len() {
83            if v[i] > t {
84                t = v[i];
85            }
86        }
87        t
88    }
89}
90
91pub fn min<T>(v: Vec<T>) -> T
92where
93    T: PartialOrd + Copy + Clone,
94{
95    let l = v.len();
96    if l == 1 {
97        v[0]
98    } else {
99        let mut t = if v[0] <= v[1] { v[0] } else { v[1] };
100        for i in 2..v.len() {
101            if v[i] < t {
102                t = v[i];
103            }
104        }
105        t
106    }
107}
108
109/// Signum function
110pub fn sgn(x: usize) -> f64 {
111    if x % 2 == 0 {
112        1f64
113    } else {
114        -1f64
115    }
116}
117
118/// Vector compare
119pub fn eq_vec(x: &[f64], y: &[f64], tol: f64) -> bool {
120    x.iter().zip(y.iter()).all(|(x, y)| (x - y).abs() <= tol)
121}
122
123// =============================================================================
124// Vec of Tuples
125// =============================================================================
126/// Auto-zip
127///
128/// # Examples
129/// ```
130/// extern crate peroxide;
131/// use peroxide::fuga::*;
132///
133/// let a = vec![1, 2, 3];
134/// let a_zipped = auto_zip(&a);
135/// assert_eq!(a_zipped, vec![(1, 2), (2, 3)]);
136/// ```
137pub fn auto_zip<T: Clone>(x: &Vec<T>) -> Vec<(T, T)> {
138    let x_head = x[0..x.len() - 1].to_vec();
139    let x_tail = x[1..x.len()].to_vec();
140    x_head.into_iter().zip(x_tail).collect()
141}
142
143/// Find the index of interval of x
144///
145/// # Examples
146/// ```
147/// extern crate peroxide;
148/// use peroxide::fuga::*;
149///
150/// let x = vec![
151///     (0, 5),
152///     (5, 7),
153///     (7, 10),
154///     (10, 15),
155///     (15, 20),
156///     (20, 30)
157/// ];
158///
159/// assert_eq!(find_interval(&x, 11), 3);
160/// ```
161pub fn find_interval<T: PartialOrd + PartialEq>(sorted_intervals: &Vec<(T, T)>, x: T) -> usize {
162    let mut i = 0;
163    let mut j = sorted_intervals.len() - 1;
164
165    // Check range
166    assert!(
167        x >= sorted_intervals[0].0,
168        "x is smaller than the smallest interval"
169    );
170    assert!(
171        x <= sorted_intervals[sorted_intervals.len() - 1].1,
172        "x is larger than the largest interval"
173    );
174
175    while i <= j {
176        let mid = (i + j) / 2;
177        if x < sorted_intervals[mid].0 {
178            j = mid - 1;
179        } else if x > sorted_intervals[mid].1 {
180            i = mid + 1;
181        } else {
182            return mid;
183        }
184    }
185    i
186}
187
188/// Generate Range of Intervals
189///
190/// # Examples
191/// ```
192/// extern crate peroxide;
193/// use peroxide::fuga::*;
194/// use std::ops::Range;
195///
196/// let x = vec![1, 2, 3, 4];
197/// let r = gen_range(&x);
198///
199/// let answer = vec![
200///     Range { start: 1, end: 2 },
201///     Range { start: 2, end: 3 },
202///     Range { start: 3, end: 4 },
203/// ];
204///
205/// assert_eq!(r, answer);
206/// ```
207pub fn gen_range<T: Clone + PartialOrd>(x: &[T]) -> Vec<Range<T>> {
208    let mut r = Vec::new();
209    for i in 0..x.len() - 1 {
210        r.push(Range {
211            start: x[i].clone(),
212            end: x[i + 1].clone(),
213        });
214    }
215    r
216}
217
218/// Generate and Zip Range of Intervals
219///
220/// # Examples
221/// ```
222/// extern crate peroxide;
223/// use peroxide::fuga::*;
224/// use std::ops::Range;
225///
226/// let x: Vec<i32> = vec![1, 2, 3, 4];
227/// let y: Vec<i32> = x.iter().map(|&t| t.pow(2)).collect();
228/// let r = zip_range(&x, &y);
229///
230/// let answer = vec![
231///     (Range { start: 1, end: 2 }, 1),
232///     (Range { start: 2, end: 3 }, 4),
233///     (Range { start: 3, end: 4 }, 9),
234/// ];
235///
236/// assert_eq!(r, answer);
237/// ```
238pub fn zip_range<T: Clone + PartialOrd, U: Clone>(x: &[T], y: &[U]) -> Vec<(Range<T>, U)> {
239    y[0..x.len() - 1]
240        .iter()
241        .enumerate()
242        .map(|(i, yi)| {
243            (
244                Range {
245                    start: x[i].clone(),
246                    end: x[i + 1].clone(),
247                },
248                yi.clone(),
249            )
250        })
251        .collect()
252}