boreholeio 0.1.0

A library for interacting with borehole.io, a subsurface data management, delivery and visualisation platform
Documentation
use super::Error;
use ndarray::{ArrayView1, Ix1, ShapeBuilder, SliceInfo, SliceInfoElem};
use std::fmt::Debug;

/// Represents numeric array sort order, if any.
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum SortOrder {
    Ascending,
    Descending,
    Unsorted,
}

/// Represents numeric array sort order, if any. Differentiates between
/// "monotonic" and "strictly monotonic" orders.
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct Monotonicity {
    pub order: SortOrder,
    pub strict: bool,
}

impl Monotonicity {
    pub fn is_ascending(&self) -> bool {
        self.order == SortOrder::Ascending
    }

    pub fn is_descending(&self) -> bool {
        self.order == SortOrder::Descending
    }

    pub fn is_monotonic(&self) -> bool {
        self.is_ascending() || self.is_descending()
    }

    pub fn is_strictly_ascending(&self) -> bool {
        self.is_ascending() && self.strict
    }

    pub fn is_strictly_descending(&self) -> bool {
        self.is_descending() && self.strict
    }

    pub fn is_strictly_monotonic(&self) -> bool {
        self.is_monotonic() && self.strict
    }
}

/// Slices an array with `ndarray`'s means and copies the resulting data into
/// new `Vec`.
pub(crate) fn slice_array<T: Clone + Debug>(
    array: &[T],
    slice_info: &SliceInfoElem,
) -> Result<Vec<T>, Error> {
    if matches!(slice_info, SliceInfoElem::NewAxis) {
        return Err("SliceInfoElem::NewAxis is not supported".into());
    }

    // Create `ArrayViewD` out of the `Vec` without copying the memory. Note
    // that `strides` are not in bytes but in array elements.
    let strided_shape = Ix1(array.len()).strides(Ix1(1));
    let view = unsafe { ArrayView1::from_shape_ptr(strided_shape, array.as_ptr()) };

    // Slice the view with `ndarray`'s means.
    let slice = slice_view1(view, slice_info)?;

    // Copy the data.
    Ok(slice.to_vec())
}

/// Just a shortcut for slicing `ArrayView1`.
pub(crate) fn slice_view1<'a, T: Clone + Debug>(
    view: ArrayView1<'a, T>,
    slice_info: &SliceInfoElem,
) -> Result<ArrayView1<'a, T>, Error> {
    let slice_info: &[SliceInfoElem] = &[*slice_info];
    let slice_info: SliceInfo<&[SliceInfoElem], Ix1, Ix1> = SliceInfo::try_from(slice_info)
        .map_err(|e| format!("Failed to convert &[SliceInfoElem] to SliceInfo: {e}"))?;
    Ok(view.slice_move(slice_info))
}