Git Product home page Git Product logo

ndarray's Introduction

ndarray

The ndarray crate provides an n-dimensional container for general elements and for numerics.

Please read the API documentation on docs.rs or take a look at the quickstart tutorial.

CI build status ndarray at crates.io Matrix chat at #rust-sci:matrix.org IRC at #rust-sci on OFTC

Highlights

  • Generic 1, 2, ..., n-dimensional arrays
  • Owned arrays and array views
  • Slicing, also with arbitrary step size, and negative indices to mean elements from the end of the axis.
  • Views and subviews of arrays; iterators that yield subviews.

Status and Lookout

  • Still iterating on and evolving the crate
    • The crate is continuously developing, and breaking changes are expected during evolution from version to version. We adopt the newest stable rust features if we need them.
  • Performance:
    • Prefer higher order methods and arithmetic operations on arrays first, then iteration, and as a last priority using indexed algorithms.
    • Efficient floating point matrix multiplication even for very large matrices; can optionally use BLAS to improve it further.

Crate Feature Flags

The following crate feature flags are available. They are configured in your Cargo.toml.

  • std

    • Rust standard library (enabled by default)

    • This crate can be used without the standard library by disabling the default std feature. To do so, use this in your Cargo.toml:

      [dependencies]
      ndarray = { version = "0.x.y", default-features = false }
      
    • The geomspace linspace logspace range std var var_axis and std_axis methods are only available when std is enabled.

  • serde

    • Enables serialization support for serde 1.x
  • rayon

    • Enables parallel iterators, parallelized methods and par_azip!.
    • Implies std
  • approx

    • Implementations of traits from version 0.5 of the [approx] crate.
  • blas

    • Enable transparent BLAS support for matrix multiplication. Uses blas-src for pluggable backend, which needs to be configured separately (see below).
  • matrixmultiply-threading

    • Enable the threading feature in the matrixmultiply package
  • portable-atomic-critical-section

    • Whether portable-atomic should use critical-section

How to use with cargo

[dependencies]
ndarray = "0.16.0"

How to enable BLAS integration

Blas integration is an optional add-on. Without BLAS, ndarray uses the matrixmultiply crate for matrix multiplication for f64 and f32 arrays (and it's always enabled as a fallback since it supports matrices of arbitrary strides in both dimensions).

Depend and link to blas-src directly to pick a blas provider. Ndarray presently requires a blas provider that provides the cblas-sys interface. If further feature selection is wanted or needed then you might need to depend directly on the backend crate's source too. The backend version must be the one that blas-src also depends on.

An example configuration using system openblas is shown below. Note that only end-user projects (not libraries) should select provider:

[dependencies]
ndarray = { version = "0.16.0", features = ["blas"] }
blas-src = { version = "0.10", features = ["openblas"] }
openblas-src = { version = "0.10", features = ["cblas", "system"] }

Using system-installed dependencies can save a long time building dependencies. An example configuration using (compiled) netlib is shown below anyway:

[dependencies]
ndarray = { version = "0.16.0", features = ["blas"] }
blas-src = { version = "0.10.0", default-features = false, features = ["netlib"] }

When this is done, your program must also link to blas_src by using it or explicitly including it in your code:

extern crate blas_src;

The following versions have been verified to work together. For ndarray 0.15 or later, there is no tight coupling to the blas-src version, so version selection is more flexible.

ndarray blas-src openblas-src netlib-src
0.16 0.10 0.10 0.8
0.15 0.8 0.10 0.8
0.15 0.7 0.9 0.8
0.14 0.6.1 0.9.0 ย 
0.13 0.2.0 0.6.0 ย 

Recent Changes

See RELEASES.md.

License

Dual-licensed to be compatible with the Rust project.

Licensed under the Apache License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 or the MIT license http://opensource.org/licenses/MIT, at your option. This file may not be copied, modified, or distributed except according to those terms.

ndarray's People

Contributors

adamreichold avatar aganders3 avatar akern40 avatar biskwikman avatar bluss avatar ethanhs avatar hameerabbasi avatar johann-cm avatar jp-ellis avatar jturner314 avatar kmolyuan avatar lazarohurtado avatar lukemathwalker avatar maciejkula avatar max-sixty avatar nilgoyette avatar robbepop avatar rth avatar sebasv avatar sparrowlii avatar ssande7 avatar stokhos avatar superfluffy avatar termoshtt avatar vasanthakumarv avatar vbarrielle avatar viniciusd avatar xd009642 avatar yuhanliin avatar zusez4 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ndarray's Issues

Add method for multiply-add aka axpy

Two reasons:

  • Blas offers this as axpy, so it can be optimized (note: axpy is for vectors, not strided matrix)
  • It's a common case.

This operation is already _available efficiently_ using .zip_mut_with:

a1.zip_mut_with(&a2, |x, &y| *x += k * y)

The question is if this is so common and the zip_mut_with so ugly that it warrants its own method.

Remove slices from array views

The &[] and &mut [] in array views are actually dead weight.

They don't serve a purpose, since the raw pointer member is all that's needed. Carrying a slice is not possible for mutable views anyway (mutable views), since disjoint mutable views can't carry slices of the whole region (would alias) and neither can carry a restricted slice of just their view (not contig.).

Can't compile 0.2.0

Compilling ndarray stopped with error
.cargo/registry/src/github.com-0a35038f75765ae4/ndarray-0.2.0/src/arrayformat.rs:46:23: 46:34 error: no method named alternate found for type &mut core::fmt::Formatter<'_> in the current scope
.cargo/registry/src/github.com-0a35038f75765ae4/ndarray-0.2.0/src/arrayformat.rs:46 if !f.alternate() {

Ubuntu 15.04
rust 1.4

Add bitflags for memory layout

We probably want to mimic numpy here by using a bitfield for keeping track of memory layout. c order, f order (both possible at the same time), as well as neither order. Maybe some blas-related property is relevant down the line. May even be a Cell field to update it on the fly? (This makes the type !Sync which we don't want..)

Constructor with specific stride

In some cases it can be nice to be able to specify a specific stride when constructing a new array (for instance to wrap over foreign data).

Meta Issue: Support for parallelized/blocked algorithms

What are your thoughts on implementing something similar to http://dask.pydata.org/en/latest/ on top of ndarrays? I suspect parallelized computations on submatrices should be pretty natural to do in the Rust framework, and it seems you've already created sub-array view functions. Do you agree?

(Community Edits below)


Actionable sub issues:

  • Send/Sync splittable array views are already present
  • Implement Rayon parallel iterator traits for Axis Iter #248 #252
  • Implement Rayon parallel iterator traits for element iterators / for Array itself #252
  • alternative methods of collecting an axis_iter to ndarray matrix #249
  • Parallel Iter for AxisChunksIter
  • Parallel support for Array::map_inplace #288
  • Parallel support for Array::map -> Array
  • Parallel lock step function application (Zip) #288

Composable generic way to achieve n-ary zips of arrays

Just brainstorming

A "builder pattern" approach may be viable here to allow n-ary zipping operations. We could even allow masking (?) which is a very valuable operation.

zip_mut(&mut a).zip(&b).zip_mut(&mut c).apply(|x, y, z| *x = *y + *z);

// This is intended to do the same as this would in numpy
// mask = c > d;
// a[mask] = b[mask]
zip_mut(&mut a).zip(&b).mask(&c, &d, <_>::gt).apply(|aelt, belt| *aelt = *belt);

crates.io ?

Once again, you happen to have just what I need ๐Ÿ˜„

Any chance this will find its way onto crates.io any time soon?

Add arithmetic operations with scalar

This is a bit tricky, since it may require some kind of scalar trait to be able to have both a + b (arrays) and a + x (x is a scalar) both available due to trait coherence.

Divide subview by scalar

I'm trying to write a simple mean function that calculates the mean of an array for a given axis. Looking at sum I cam up with the following, but now I can't figure out how to divide the sum by the number of elements.
If I try normal divison I get: error: the trait 'core::ops::Div<usize>' is not implemented for the type 'A'. If I try the idiv version it tells me error: mismatched types: expected 'A', found 'usize' (expected type parameter, found usize) [E0308]

Do you have any hints?

trait Stats<A, S, D>
        where A: Clone + Add<Output = A> + Div<Output = A>,
              D: RemoveAxis
{
    fn mean(&self, Axis) -> OwnedArray<A, <D as RemoveAxis>::Smaller>;
}

impl<A, S, D> Stats<A, S, D> for ArrayBase<S, D>
    where A: Clone + Add<Output = A> + Div<Output = A> + Div,
          S: Data<Elem = A>,
          D: Dimension + RemoveAxis
{
    fn mean(&self, axis: Axis) -> OwnedArray<A, <D as RemoveAxis>::Smaller> {
        let n = self.shape()[axis.axis()];
        println!("{:?}", self.shape());
        let mut res = self.subview(axis, 0).to_owned();
        for i in 1..n {
            let view = self.subview(axis, i);
            res.iadd(&view);
        }
        // res.idiv(&arr0::<A>(n));
        res / n
    }
}

Non-assignment binary operations shouldn't mutate input

In the example at the bottom, addition of two arrays yields a new one, but also mutates one of the inputs. This is because the add() function in the Add trait is defined in terms of the in-place iadd() (from the macro impl_binary_op macro):

impl<'a, A, S, S2, D, E> $trt<&'a ArrayBase<S2, E>> for ArrayBase<S, D>
    where A: Clone + $trt<A, Output=A>,
          S: DataMut<Elem=A>,
          S2: Data<Elem=A>,
          D: Dimension,
          E: Dimension,
{
    type Output = ArrayBase<S, D>;
    fn $mth (mut self, rhs: &ArrayBase<S2, E>) -> ArrayBase<S, D>
    {
        self.$imth(rhs);
        self
    }
}

This is fine, if self is an OwnedArray or an Array because they are consumed anyways, but if instead an ArrayViewMut is passed in, the underlying data changes. Is this intended? I think one shouldn't expect the array to get changed when addition is performed on a view.

extern crate ndarray;

use ndarray::{Array,OwnedArray};

fn main() {
    let r = 0..4;
    let v = r.map(|x| x as f64).collect::<Vec<_>>();

    let mut a = OwnedArray::from_vec(v.clone()).into_shape((2,2)).unwrap();
    let b = OwnedArray::from_vec(v.clone()).into_shape((2,2)).unwrap();

    let bv = b.view();

    {
        let x = a.view_mut() + bv;
        println!("{:?}", x);
    }

    println!("{:?}", a);
}

Strongly typed `Axis` arguments

We could have strongly typed Axis arguments (instead of current usize).

It even allows mixing dynamically bounds checked axis numbers and statically checked ones:

.subview(Axis(0), 1) vs. .subview(Axis0, 1) would both be possible at the same time.

Implementing Index<Axis> for Dimension

This would allow using a.dim()[Axis(0)], which is not that much of a win. However, when implementing a method that takes an Axis as an argument, this could be a real win:
a.dim().slice()[axis.axis()] vs a.dim()[axis].

What do you think?

"0.4.0-alpha.1" on cargo.io fails to download, please reup with new cargo

Building version 0.4.0-alpha.1 with the dependency ndarray = "~0.4.0" in Cargo.toml gives the following error:

% cargo build --verbose
unable to get packages from source

Caused by:
  failed to unpack package `ndarray v0.4.0-alpha.1`

Caused by:
  No such file or directory (os error 2)
zsh: exit 101   cargo build --verbose

Apparently this was an issue with the recent cargo build and is now fixed. According to this comment, crates for which this problem still occurs should be reuploaded with a recent cargo version.

You put ndarray onto crates.io just a few days before this error report was posted, so I think this might be related.

BLAS: Investigate validity of shared / mutable array views with interleaved data

Consider this case:

If you're interested, a tricky question remains, imagine a 4 x 4 matrix in row major order. The columns of the matrix are technically both F-order and C-order since they are one dimensional (but with a leading dimension of 4).

Anyway, adjacent columns do not overlap, but their memory interleaves very closely. Is this compatible with blas? ๐Ÿ˜„

Add a float trait based on `Float`

The idea is to add a trait for just f32, f64 that allows access to all relevant ndarray API, as long as the element has that trait.

We now have Any and ScalarOperand involved in various bounds for technical reasons, so the trait would for example include those.

Support IxDyn/vec![] dimension better

  • mutate in place stepping for the iterator
  • Pass index as slice
  • allow indexing with regular arrays (#225)
  • No allocation for small case #285 #301
  • .zip_mut_with improvement reduces binary operation custom stride case overhead for ixdyn #292
  • Fancier slicing, selecting subviews #215

32 bit vs. 64 bit indexing

Yesterday I was window shopping for new computer languages and I found rust which looks awesome if not yet mainstream. I like array-based approaches to certain problems, so I checked for ndarray support and found this github library. Nice!

Anyway, I noticed that this crate uses u32 for indexing.
http://bluss.github.io/rust-ndarray/doc/ndarray/struct.Array.html
In numpy it is increasingly common for users to have large arrays that cannot be indexed by such small integer types. I personally don't have enough RAM for this, but this could change in the future. Or you might want the same interface for arrays on disk as in RAM, or the same interface for sparse arrays that could more easily hold more entries. But of course using unnecessarily large integer types for indexing slows the code and increases the memory usage...

Less general arithmetic operations and numerics

99% of numerical support exists to support floating-point f32 and f64.

We can make arithmetic and numerics less generic (stricter trait bounds).

As it is now, sum() is for example implemented for all elements where A: Clone + Add<A, Target=A>.
Arithmetic operations like Sub are implemented with similar Clone + Sub bounds.

We would benefit some if we could make these implementations stricter. For example using A: Copy allows us to use uninitialized memory efficiently (important for whenever you allocate a new array for the result).

Could not broadcast array from shape: [2] to: [2, 1]

Using slices, I want to set the columns or rows of the 2ร—2 matrix (i.e. Array) a to the vectors u or v, respectively. This works when slicing along the first axis (getting row-slices), but not along the second:

#[macro_use(s)]
extern crate ndarray;

use ndarray::OwnedArray;

fn main() {
    let u: Vec<f64> = vec![1.,2.];
    let v: Vec<f64> = vec![3.,4.];

    let mut a = OwnedArray::from_elem((2,2), 0f64);

    // Works
    a.slice_mut(s![0..1, ..]).assign(&OwnedArray::from_vec(u.clone()));
    a.slice_mut(s![1..2, ..]).assign(&OwnedArray::from_vec(v.clone()));

    // Could not broadcast array from shape: [2] to: [2, 1]
    a.slice_mut(s![.., 0..1]).assign(&OwnedArray::from_vec(u.clone()));
    a.slice_mut(s![.., 1..2]).assign(&OwnedArray::from_vec(v.clone()));
}

I suppose the problem is that ndarray can broadcast from [2] to [1,2], but not to the reverse.

alpha versioning looks problematic with crates.io

I was trying to make a crate depend on the version 0.4.0-alpha.1 that's on crates.io, but if I specify the dependency as ndarray = "0.4" I get the cargo error unable to get packages from source, and if I try to put the exact version number cargo errs out telling me it can't parse the cargo.toml.

However this works fine when specifying the dependency via git.

So maybe alpha versions should not be uploaded to crates.io as it seems they can"t be used from there.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.