ndarray 0.8.4

An N-dimensional array for general elements and for numerics. Lightweight array views and slicing; views support chunking and splitting.
Documentation
#![feature(test)]

extern crate test;
use test::Bencher;

#[macro_use(s, azip)]
extern crate ndarray;
use ndarray::prelude::*;
use ndarray::{Zip, FoldWhile};

#[bench]
fn iter_sum_2d_regular(bench: &mut Bencher)
{
    let a = Array::<i32, _>::zeros((64, 64));
    bench.iter(|| {
        a.iter().fold(0, |acc, &x| acc + x)
    });
}

#[bench]
fn iter_sum_2d_cutout(bench: &mut Bencher)
{
    let a = Array::<i32, _>::zeros((66, 66));
    let av = a.slice(s![1..-1, 1..-1]);
    let a = av;
    bench.iter(|| {
        a.iter().fold(0, |acc, &x| acc + x)
    });
}

#[bench]
fn iter_all_2d_cutout(bench: &mut Bencher)
{
    let a = Array::<i32, _>::zeros((66, 66));
    let av = a.slice(s![1..-1, 1..-1]);
    let a = av;
    bench.iter(|| {
        a.iter().all(|&x| x >= 0)
    });
}

#[bench]
fn iter_sum_2d_transpose(bench: &mut Bencher)
{
    let a = Array::<i32, _>::zeros((66, 66));
    let a = a.t();
    bench.iter(|| {
        a.iter().fold(0, |acc, &x| acc + x)
    });
}

#[bench]
fn iter_filter_sum_2d_u32(bench: &mut Bencher)
{
    let a = Array::linspace(0., 1., 256).into_shape((16, 16)).unwrap();
    let b = a.mapv(|x| (x * 100.) as u32);
    bench.iter(|| {
        b.iter().filter(|&&x| x < 75).fold(0, |acc, &x| acc + x)
    });
}

#[bench]
fn iter_filter_sum_2d_f32(bench: &mut Bencher)
{
    let a = Array::linspace(0., 1., 256).into_shape((16, 16)).unwrap();
    let b = a * 100.;
    bench.iter(|| {
        b.iter().filter(|&&x| x < 75.).fold(0., |acc, &x| acc + x)
    });
}

#[bench]
fn iter_filter_sum_2d_stride_u32(bench: &mut Bencher)
{
    let a = Array::linspace(0., 1., 256).into_shape((16, 16)).unwrap();
    let b = a.mapv(|x| (x * 100.) as u32);
    let b = b.slice(s![.., ..;2]);
    bench.iter(|| {
        b.iter().filter(|&&x| x < 75).fold(0, |acc, &x| acc + x)
    });
}

#[bench]
fn iter_filter_sum_2d_stride_f32(bench: &mut Bencher)
{
    let a = Array::linspace(0., 1., 256).into_shape((16, 16)).unwrap();
    let b = a * 100.;
    let b = b.slice(s![.., ..;2]);
    bench.iter(|| {
        b.iter().filter(|&&x| x < 75.).fold(0., |acc, &x| acc + x)
    });
}

const ZIPSZ: usize = 10_000;

#[bench]
fn scalar_sum_3_std_zip1(bench: &mut Bencher)
{
    let a = vec![1; ZIPSZ];
    let b = vec![1; ZIPSZ];
    let c = vec![1; ZIPSZ];
    bench.iter(|| {
        a.iter().zip(b.iter().zip(&c)).fold(0, |acc, (&a, (&b, &c))| {
            acc + a + b + c
        })
    });
}

#[bench]
fn scalar_sum_3_std_zip2(bench: &mut Bencher)
{
    let a = vec![1; ZIPSZ];
    let b = vec![1; ZIPSZ];
    let c = vec![1; ZIPSZ];
    bench.iter(|| {
        a.iter().zip(b.iter()).zip(&c).fold(0, |acc, ((&a, &b), &c)| {
            acc + a + b + c
        })
    });
}

#[bench]
fn scalar_sum_3_std_zip3(bench: &mut Bencher)
{
    let a = vec![1; ZIPSZ];
    let b = vec![1; ZIPSZ];
    let c = vec![1; ZIPSZ];
    bench.iter(|| {
        let mut s = 0;
        for ((&a, &b), &c) in a.iter().zip(b.iter()).zip(&c) {
            s += a + b + c
        }
        s
    });
}

#[bench]
fn vector_sum_3_std_zip(bench: &mut Bencher)
{
    let a = vec![1.; ZIPSZ];
    let b = vec![1.; ZIPSZ];
    let mut c = vec![1.; ZIPSZ];
    bench.iter(|| {
        for ((&a, &b), c) in a.iter().zip(b.iter()).zip(&mut c) {
            *c += a + b;
        }
    });
}

#[bench]
fn scalar_sum_3_azip(bench: &mut Bencher)
{
    let a = vec![1; ZIPSZ];
    let b = vec![1; ZIPSZ];
    let c = vec![1; ZIPSZ];
    bench.iter(|| {
        let mut s = 0;
        azip!(a, b, c in {
            s += a + b + c;
        });
        s
    });
}

#[bench]
fn scalar_sum_3_azip_fold(bench: &mut Bencher)
{
    let a = vec![1; ZIPSZ];
    let b = vec![1; ZIPSZ];
    let c = vec![1; ZIPSZ];
    bench.iter(|| {
        Zip::from(&a).and(&b).and(&c).fold_while(0, |acc, &a, &b, &c| {
            FoldWhile::Continue(acc + a + b + c)
        }).into_inner()
    });
}

#[bench]
fn vector_sum_3_azip(bench: &mut Bencher)
{
    let a = vec![1.; ZIPSZ];
    let b = vec![1.; ZIPSZ];
    let mut c = vec![1.; ZIPSZ];
    bench.iter(|| {
        azip!(a, b, mut c in {
            *c += a + b;
        });
    });
}

#[bench]
fn vector_sum_3_zip_unchecked(bench: &mut Bencher)
{
    let a = vec![1.; ZIPSZ];
    let b = vec![1.; ZIPSZ];
    let mut c = vec![1.; ZIPSZ];
    bench.iter(|| {
        for i in 0..c.len() {
            unsafe {
                *c.get_unchecked_mut(i) += *a.get_unchecked(i) + *b.get_unchecked(i);
            }
        }
    });
}

// index iterator size
const ISZ: usize = 16;

#[bench]
fn indexed_iter_3d_ix3(bench: &mut Bencher) {
    let mut a = Array::<f64, _>::zeros((ISZ, ISZ, ISZ));
    for ((i, j, k), elt) in a.indexed_iter_mut() {
        *elt = (i + 100 * j + 10000 * k) as _;
    }

    bench.iter(|| {
        for (i, &elt) in a.indexed_iter() {
            assert!(a[i] == elt);
        }
    })
}

#[bench]
fn indexed_iter_3d_dyn(bench: &mut Bencher) {
    let mut a = Array::<f64, _>::zeros((ISZ, ISZ, ISZ));
    for ((i, j, k), elt) in a.indexed_iter_mut() {
        *elt = (i + 100 * j + 10000 * k) as _;
    }
    let a = a.into_shape(&[ISZ; 3][..]).unwrap();

    bench.iter(|| {
        for (i, &elt) in a.indexed_iter() {
            assert!(a[i] == elt);
        }
    })
}