libreda_interp/
lib.rs

1// Copyright (c) 2021-2021 Thomas Kramer.
2// SPDX-FileCopyrightText: 2022 Thomas Kramer <code@tkramer.ch>
3//
4// SPDX-License-Identifier: GPL-3.0-or-later
5
6//! Interpolation of one and two dimensional data.
7
8#![deny(missing_docs)]
9
10use std::cmp::Ordering;
11
12pub mod interp1d;
13pub mod interp2d;
14
15/// Find closest grid points.
16fn find_closest_neighbours_indices<C>(v: &Vec<C>, x: C) -> (usize, usize)
17where
18    C: PartialOrd,
19{
20    let idx = match v.binary_search_by(|a| {
21        if *a < x {
22            Ordering::Less
23        } else if *a == x {
24            Ordering::Equal
25        } else {
26            Ordering::Greater
27        }
28    }) {
29        Ok(i) => i,
30        Err(i) => i.max(1) - 1,
31    };
32
33    if idx == v.len() - 1 {
34        (idx - 1, idx)
35    } else {
36        (idx, idx + 1)
37    }
38}
39
40#[test]
41fn test_find_closest_neighbours_indices() {
42    let v = vec![0., 1., 2.];
43    assert_eq!(find_closest_neighbours_indices(&v, -0.1), (0, 1));
44    assert_eq!(find_closest_neighbours_indices(&v, 0.), (0, 1));
45    assert_eq!(find_closest_neighbours_indices(&v, 0.01), (0, 1));
46    assert_eq!(find_closest_neighbours_indices(&v, 0.99), (0, 1));
47    assert_eq!(find_closest_neighbours_indices(&v, 1.0), (1, 2));
48    assert_eq!(find_closest_neighbours_indices(&v, 1.99), (1, 2));
49    assert_eq!(find_closest_neighbours_indices(&v, 2.99), (1, 2));
50}
51
52fn is_monotonic<T: PartialOrd, I: IntoIterator<Item = T>>(i: I) -> bool {
53    let mut it = i.into_iter();
54    if let Some(prev) = it.next() {
55        let mut prev = prev;
56        for n in it {
57            if prev <= n {
58            } else {
59                return false;
60            }
61            prev = n;
62        }
63    }
64    true
65}