convolician 0.1.0

Fast, easy matrix gradients
Documentation
use ndarray::prelude::*;

pub fn central_difference_x(m: &Array2<u8>) -> Array2<i16> {
    let mut d_x: Array2<i16> = unsafe { Array2::uninitialized(m.dim()) };

    // using mirror boundary conditions i.e. 'ghost points' immediately
    // to the left and right of m have the same value as the first and
    // last values of m along the axis of convolution
    apply_mirror_boundary_x(m, &mut d_x);

    // CENTRE
    let mut centre = d_x.slice_mut(s![.., 1..-1]);
    centre.assign(&m.slice(s![.., 2.. ]).mapv(|el| el as i16));
    centre -= &m.slice(s![.., ..-2]).mapv(|el| el as i16);

    d_x
}

pub fn central_difference_x_2(m: &Array2<u8>) -> Array2<i16> {
    let mut d_x: Array2<i16> = unsafe { Array2::uninitialized(m.dim()) };

    // using mirror boundary conditions i.e. 'ghost points' immediately
    // to the left and right of m have the same value as the first and
    // last values of m along the axis of convolution
    apply_mirror_boundary_x(m, &mut d_x);

    // CENTRE
    // let temp = M.slice(s![..,2..-1]) - M.slice(s![..,..-2]);
    let mut centre = d_x.slice_mut(s![.., 1..-1]);
    let before = &m.slice(s![.., ..-2]);
    let after  = &m.slice(s![.., 2.. ]);
    // azip!(mut centre, before, after in {*centre = after - before});
    // Zip::from(centre).and(before).and(after).apply(|a, b, c| {
    //     *a = b + c;
    // });
    d_x
}

fn apply_mirror_boundary_x(m: &Array2<u8>, d_x: &mut Array2<i16>) {
    // START
    let mut start = d_x.slice_mut(s![.., 0]);
    start.assign(&m.slice(s![.., 1]).mapv(|el| el as i16));
    start -= &m.slice(s![.., 0]).mapv(|el| el as i16);

    // END
    let mut end = d_x.slice_mut(s![.., -1]);
    end.assign(&m.slice(s![.., -1]).mapv(|el| el as i16));
    end -= &m.slice(s![.., -2]).mapv(|el| el as i16);
}

// fn laplacian(M: &ArrayView2<u8>) -> Array2<i16> {
//     -4. * &M.slice(s![1..-1, 1..-1])
//     + M.slice(s![ ..-2, 1..-1])
//     + M.slice(s![1..-1,  ..-2])
//     + M.slice(s![1..-1, 2..  ])
//     + M.slice(s![2..  , 1..-1])
// }

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_deleteme() {
        let m = arr2(&[[1, 2, 3],
                     [4, 5, 6]]);
        let v = &m.slice(s![.., 1..-1]);
        println!("Hello {:?}", v);
    }

    #[test]
    fn test_central_difference_x() {
      let m: Array2<u8> = arr2(&[[1, 3, 6],
                                 [6, 3, 1]]);

      let d_x = central_difference_x(&m);
      let expected = arr2(&[[ 2,  5,  3],
                            [-3, -5, -2]]);

      assert_eq!(d_x, expected);
    }

    fn test_central_difference_x_negative_gradients() {
        
    }

    fn test_central_difference_x_one_column() {

    }

    fn test_central_difference_x_zero_columns() {

    }
}

// #![feature(test)]

// extern crate test;
// use test::Bencher;

// #[bench]
// fn bench_workload(b: &mut Bencher) {
//     b.iter(|| workload());
// }