From 1be874e1924290f513bcd889284dc19635a67db7 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Sun, 16 Feb 2020 19:56:45 +0100 Subject: [PATCH 01/14] Add quick start readme --- README-quick-start.md | 590 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 590 insertions(+) create mode 100644 README-quick-start.md diff --git a/README-quick-start.md b/README-quick-start.md new file mode 100644 index 000000000..2f9a7857c --- /dev/null +++ b/README-quick-start.md @@ -0,0 +1,590 @@ +# Quickstart tutorial + +If you are familiar with Python Numpy, do check out this [For Numpy User Doc](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) +after you go through this tutorial. + +You can use [play.integer32.com](https://play.integer32.com/) site to immediately trying out the following examples. + +## The Basics + +Just create your first 2x3 floating-point ndarray +```rust +use ndarray::prelude::*; + +fn main() { + let a = array![ + [1.,2.,3.], + [4.,5.,6.], + ]; + assert_eq!(a.ndim(), 2); // get the number of dimensions of array a + assert_eq!(a.len(), 6); // get the number of elements in array a + assert_eq!(a.shape(), [2, 3]); // get the shape of array a + assert_eq!(a.is_empty(), false); // check if the array has zero elements + + println!("{:?}", a); +} +``` +This code will create a simple array and output to stdout: +``` +[[1.0, 2.0, 3.0], + [4.0, 5.0, 6.0]], shape=[2, 3], strides=[3, 1], layout=C (0x1), const ndim=2 +``` + +## Array Creation + +### Element type and dimensionality + +Now let's create more arrays. How about try make a zero array with dimension of (3, 2, 4)? + +```rust +use ndarray::prelude::*; +use ndarray::Array; +fn main() { + let a = Array::zeros((3, 2, 4).f()); + println!("{:?}", a); +} +``` +gives +``` +| let a = Array::zeros((3, 2, 4).f()); +| - ^^^^^^^^^^^^ cannot infer type for type parameter `A` +``` +Note that the compiler needs to infer the element type and dimensionality from context. In this +case the compiler failed to do that. Now we give it the type and let it infer dimensionality + +```rust +use ndarray::prelude::*; +use ndarray::Array; +fn main() { + let a = Array::::zeros((3, 2, 4).f()); + println!("{:?}", a); +} +``` +and now it works: +``` +[[[0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0]], + + [[0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0]], + + [[0.0, 0.0, 0.0, 0.0], + [0.0, 0.0, 0.0, 0.0]]], shape=[3, 2, 4], strides=[1, 3, 6], layout=F (0x2), const ndim=3 +``` + +We can also specify it's dimensionality + +```rust +use ndarray::prelude::*; +use ndarray::{Array, Ix3}; +fn main() { + let a = Array::::zeros((3, 2, 4).f()); + println!("{:?}", a); +} +``` +`Ix3` stands for 3D array. + +And now we are type checked. Try change the above code to `Array::::zeros((3, 2, 4, 5).f());` +and compile, see what happens. + +### Some common create helper functions +`linspace` - Create a 1-D array with 21 elements with values 0., …, 5. +```rust +use ndarray::prelude::*; +use ndarray::{Array, Ix3}; +fn main() { + let a = Array::::linspace(0., 5., 11); + println!("{:?}", a); +} +``` +The output is: +``` +[0.0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 3.5, 4.0, 4.5, 5.0], shape=[11], strides=[1], layout=C | F (0x3), const ndim=1 +``` + +And there are also `range`, `logspace`, `ones`, `eye` and so on you can choose to use. + +## Basic operations + +```rust +use ndarray::prelude::*; +use ndarray::Array; +use std::f64::INFINITY as inf; + +fn main() { + let a = array![ + [10.,20.,30., 40.,], + ]; + let b = Array::range(0., 4., 1.); // [0., 1., 2., 3, ] + + assert_eq!(&a + &b, array![[10., 21., 32., 43.,]]); // Allocates a new array. Note the explicit `&`. + assert_eq!(&a - &b, array![[10., 19., 28., 37.,]]); + assert_eq!(&a * &b, array![[0., 20., 60., 120.,]]); + assert_eq!(&a / &b, array![[inf, 20., 15., 13.333333333333334,]]); +} +``` + +And try remove all the `&` sign in front of `a` and `b`, see if it still compiles. Why? + +Note that +* `&A @ &A` which produces a new `Array` +* `B @ A` which consumes `B`, updates it with the result, and returns it +* `B @ &A` which consumes `B`, updates it with the result, and returns it +* `C @= &A` which performs an arithmetic operation in place + +More info checkout https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#arithmetic-operations + +Some operations have `_axis` appended on the function name that can take in `Axis` as parameters, +such as `sum_axis`: + +```rust +use ndarray::{aview0, aview1, arr2, Axis}; + +fn main() { + let a = arr2(&[[1., 2., 3.], + [4., 5., 6.]]); + assert!( + a.sum_axis(Axis(0)) == aview1(&[5., 7., 9.]) && + a.sum_axis(Axis(1)) == aview1(&[6., 15.]) && + + a.sum_axis(Axis(0)).sum_axis(Axis(0)) == aview0(&21.) && + a.sum_axis(Axis(0)).sum_axis(Axis(0)) == aview0(&a.sum()) + ); +} +``` + +### Matrix product + +```rust +use ndarray::prelude::*; +use ndarray::Array; + +fn main() { + let a = array![ + [10.,20.,30., 40.,], + ]; + let b = Array::range(0., 4., 1.); // b = [0., 1., 2., 3, ] + println!("a shape {:?}", &a.shape()); + println!("b shape {:?}", &b.shape()); + + let b = b.into_shape((4,1)).unwrap(); // reshape b to shape [4, 1] + println!("b shape {:?}", &b.shape()); + + println!("{}", a.dot(&b)); // [1, 4] x [4, 1] -> [1, 1] + println!("{}", a.t().dot(&b.t())); // [4, 1] x [1, 4] -> [4, 4] +} +``` +The output is: +``` +a shape [1, 4] +b shape [4] +b shape after reshape [4, 1] +[[200]] +[[0, 10, 20, 30], + [0, 20, 40, 60], + [0, 30, 60, 90], + [0, 40, 80, 120]] +``` + +## Indexing, Slicing and Iterating +One-dimensional arrays can be indexed, sliced and iterated over, much like `numpy` arrays + +```rust +use ndarray::prelude::*; +use ndarray::Array; + +fn main() { + let a = Array::range(0., 10., 1.); + + let mut a = a.mapv(|a: f64| a.powi(3)); // numpy equivlant of `a ** 3`; https://doc.rust-lang.org/nightly/std/primitive.f64.html#method.powi + + println!("{}", a); + + println!("{}", a[[2]]); + println!("{}", a.slice(s![2])); + + println!("{}", a.slice(s![2..5])); + + a.slice_mut(s![..6;2]).fill(1000.); // numpy equivlant of `a[:6:2] = 1000` + println!("{}", a); + + for i in a.iter() { + print!("{}, ", i.powf(1./3.)) + } +} +``` +The output is: +``` +[0, 1, 8, 27, 64, 125, 216, 343, 512, 729] +8 +8 +[8, 27, 64] +[1000, 1, 1000, 27, 1000, 125, 216, 343, 512, 729] +9.999999999999998, 1, 9.999999999999998, 3, 9.999999999999998, 4.999999999999999, 5.999999999999999, 6.999999999999999, 7.999999999999999, 8.999999999999998, +``` + +More info about iteration see [Loops, Producers, and Iterators](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#loops-producers-and-iterators) + +Let's try a 3D array having element type as `isize`. This is how you can indexing +```rust +use ndarray::prelude::*; + +fn main() { + let a = array![ + [[ 0, 1, 2], // a 3D array 2 x 2 x 3 + [ 10, 12, 13]], + + [[100,101,102], + [110,112,113]] + ]; + + let a = a.mapv(|a: isize| a.pow(1)); // numpy equivlant of `a ** 1`; + // This line does nothing but illustrate mapv with isize type + println!("a -> \n{}\n", a); + + println!("`a.slice(s![1, .., ..])` -> \n{}\n", a.slice(s![1, .., ..])); + + println!("`a.slice(s![.., .., 2])` -> \n{}\n", a.slice(s![.., .., 2])); + + println!("`a.slice(s![.., 1, 0..2])` -> \n{}\n", a.slice(s![.., 1, 0..2])); + + println!("`a.iter()` ->"); + for i in a.iter() { + print!("{}, ", i) // flat out to every element + } + + println!("\n\n`a.outer_iter()` ->"); + for i in a.outer_iter() { + print!("row: {}, \n", i) // iterate through first dimension + } +} +``` +The output is: +``` +a -> +[[[0, 1, 2], + [10, 12, 13]], + + [[100, 101, 102], + [110, 112, 113]]] + +`a.slice(s![1, .., ..])` -> +[[100, 101, 102], + [110, 112, 113]] + +`a.slice(s![.., .., 2])` -> +[[2, 13], + [102, 113]] + +`a.slice(s![.., 1, 0..2])` -> +[[10, 12], + [110, 112]] + +`a.iter()` -> +0, 1, 2, 10, 12, 13, 100, 101, 102, 110, 112, 113, + +`a.outer_iter()` -> +row: [[0, 1, 2], + [10, 12, 13]], +row: [[100, 101, 102], + [110, 112, 113]], +``` + +## Shape Manipulation + +### Changing the shape of an array +The shape of an array can be changed with `into_shape` method. + +````rust +use ndarray::prelude::*; +use ndarray::Array; +use std::iter::FromIterator; +// use ndarray_rand::RandomExt; +// use ndarray_rand::rand_distr::Uniform; + +fn main() { + // Or you may use ndarray_rand crate to generate random arrays + // let a = Array::random((2, 5), Uniform::new(0., 10.)); + + let a = array![ + [3., 7., 3., 4.], + [1., 4., 2., 2.], + [7., 2., 4., 9.]]; + + println!("a = \n{:?}\n", a); + + // use trait FromIterator to flatten a matrix to a vector + let b = Array::from_iter(a.iter()); + println!("b = \n{:?}\n", b); + + let c = b.into_shape([6, 2]).unwrap(); // consume b and generate c with new shape + println!("c = \n{:?}", c); +} +```` +The output is: +``` +a = +[[3.0, 7.0, 3.0, 4.0], + [1.0, 4.0, 2.0, 2.0], + [7.0, 2.0, 4.0, 9.0]], shape=[3, 4], strides=[4, 1], layout=C (0x1), const ndim=2 + +b = +[3.0, 7.0, 3.0, 4.0, 1.0, 4.0, 2.0, 2.0, 7.0, 2.0, 4.0, 9.0], shape=[12], strides=[1], layout=C | F (0x3), const ndim=1 + +c = +[[3.0, 7.0], + [3.0, 4.0], + [1.0, 4.0], + [2.0, 2.0], + [7.0, 2.0], + [4.0, 9.0]], shape=[6, 2], strides=[2, 1], layout=C (0x1), const ndim=2 +``` + +### Stacking together different arrays + +Macro `stack!` is helpful for stacking arrays: +```rust +use ndarray::prelude::*; +use ndarray::{Array, Axis, stack}; + +fn main() { + + let a = array![ + [9., 7.], + [5., 2.]]; + + let b = array![ + [1., 9.], + [5., 1.]]; + + println!("a vstack b = \n{:?}\n", stack![Axis(0), a, b]); + + println!("a hstack b = \n{:?}\n", stack![Axis(1), a, b]); +} +``` +The output is: +``` +a vstack b = +[[9.0, 7.0], + [5.0, 2.0], + [1.0, 9.0], + [5.0, 1.0]], shape=[4, 2], strides=[2, 1], layout=C (0x1), const ndim=2 + +a hstack b = +[[9.0, 7.0, 1.0, 9.0], + [5.0, 2.0, 5.0, 1.0]], shape=[2, 4], strides=[4, 1], layout=C (0x1), const ndim=2 +``` + +### Splitting one array into several smaller ones + +More to see here [ArrayView::split_at](https://docs.rs/ndarray/latest/ndarray/type.ArrayView.html#method.split_at) +```rust +use ndarray::prelude::*; +use ndarray::Axis; + +fn main() { + + let a = array![ + [6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.], + [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]]; + + let (s1, s2) = a.view().split_at(Axis(0), 1); + println!("Split a from Axis(0), at index 1:"); + println!("s1 = \n{}", s1); + println!("s2 = \n{}\n", s2); + + + let (s1, s2) = a.view().split_at(Axis(1), 4); + println!("Split a from Axis(1), at index 4:"); + println!("s1 = \n{}", s1); + println!("s2 = \n{}\n", s2); +} +``` +The output is: +``` +Split a from Axis(0), at index 1: +s1 = +[[6, 7, 6, 9, 0, 5, 4, 0, 6, 8, 5, 2]] +s2 = +[[8, 5, 5, 7, 1, 8, 6, 7, 1, 8, 1, 0]] + +Split a from Axis(1), at index 4: +s1 = +[[6, 7, 6, 9], + [8, 5, 5, 7]] +s2 = +[[0, 5, 4, 0, 6, 8, 5, 2], + [1, 8, 6, 7, 1, 8, 1, 0]] + +``` + +## Copies and Views +### View, Ref or Shallow Copy +As in Rust we have owner ship, so we cannot simply +update an element of an array while we have a +shared view of it. This will help us write more +robust code than numpy. + +```rust +use ndarray::prelude::*; +use ndarray::{Array, Axis}; + +fn main() { + + let mut a = Array::range(0., 12., 1.).into_shape([3 ,4]).unwrap(); + println!("a = \n{}\n", a); + + { + let (s1, s2) = a.view().split_at(Axis(1), 2); + + // with s as a view sharing the ref of a, we cannot update a here + // a.slice_mut(s![1, 1]).fill(1234.); + + println!("Split a from Axis(0), at index 1:"); + println!("s1 = \n{}", s1); + println!("s2 = \n{}\n", s2); + } + + // now we can update a again here, as views of s1, s2 are dropped already + a.slice_mut(s![1, 1]).fill(1234.); + + let (s1, s2) = a.view().split_at(Axis(1), 2); + println!("Split a from Axis(0), at index 1:"); + println!("s1 = \n{}", s1); + println!("s2 = \n{}\n", s2); +} +``` +The output is: +``` +a = +[[0, 1, 2, 3], + [4, 5, 6, 7], + [8, 9, 10, 11]] + +Split a from Axis(0), at index 1: +s1 = +[[0, 1], + [4, 5], + [8, 9]] +s2 = +[[2, 3], + [6, 7], + [10, 11]] + +Split a from Axis(0), at index 1: +s1 = +[[0, 1], + [4, 1234], + [8, 9]] +s2 = +[[2, 3], + [6, 7], + [10, 11]] +``` + +### Deep Copy +As the usual way in Rust, a `clone()` call will +make a copy of your array: +```rust +use ndarray::prelude::*; +use ndarray::Array; + +fn main() { + + let mut a = Array::range(0., 4., 1.).into_shape([2 ,2]).unwrap(); + let b = a.clone(); + + println!("a = \n{}\n", a); + println!("b clone of a = \n{}\n", a); + + a.slice_mut(s![1, 1]).fill(1234.); + + println!("a updated..."); + println!("a = \n{}\n", a); + println!("b clone of a = \n{}\n", b); +} +``` + +The output is: +``` +a = +[[0, 1], + [2, 3]] + +b clone of a = +[[0, 1], + [2, 3]] + +a updated... +a = +[[0, 1], + [2, 1234]] + +b clone of a = +[[0, 1], + [2, 3]] +``` + +## Broadcasting + +Arrays support limited broadcasting, where arithmetic operations with array operands of different sizes can be carried out by repeating the elements of the smaller dimension array. + +```rust +use ndarray::prelude::*; + +fn main() { + let a = array![ + [1., 1.], + [1., 2.], + [0., 3.], + [0., 4.]]; + + let b = array![[0., 1.]]; + + let c = array![ + [1., 2.], + [1., 3.], + [0., 4.], + [0., 5.]]; + + // We can add because the shapes are compatible even if not equal. + // The `b` array is shape 1 × 2 but acts like a 4 × 2 array. + assert!(c == a + b); +} +``` + +See [.broadcast()](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.broadcast) for a more detailed description. + +And there is a short example of it: +```rust +use ndarray::prelude::*; + +fn main() { + let a = array![ + [1., 2.], + [3., 4.], + ]; + + let b = a.broadcast((3, 2, 2)).unwrap(); + println!("shape of a is {:?}", a.shape()); + println!("a is broadcased to 3x2x2 = \n{}", b); +} +``` +The output is: +``` +shape of a is [2, 2] +a is broadcased to 3x2x2 = +[[[1, 2], + [3, 4]], + + [[1, 2], + [3, 4]], + + [[1, 2], + [3, 4]]] +``` + +## Want to learn more? +Please checkout these docs for more information +* [`ArrayBase` doc page](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html) +* [`ndarray` for `numpy` user doc page](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) \ No newline at end of file From fdcbf91d92b55ec7b0001a7bc0931e3ebe4a5f7d Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:08:50 +0100 Subject: [PATCH 02/14] Fix up Co-Authored-By: Luca Palmieri --- README-quick-start.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index 2f9a7857c..0dd4a4343 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -3,7 +3,7 @@ If you are familiar with Python Numpy, do check out this [For Numpy User Doc](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) after you go through this tutorial. -You can use [play.integer32.com](https://play.integer32.com/) site to immediately trying out the following examples. +You can use [play.integer32.com](https://play.integer32.com/) to immediately try out the examples. ## The Basics @@ -587,4 +587,4 @@ a is broadcased to 3x2x2 = ## Want to learn more? Please checkout these docs for more information * [`ArrayBase` doc page](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html) -* [`ndarray` for `numpy` user doc page](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) \ No newline at end of file +* [`ndarray` for `numpy` user doc page](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) From d6ab8b5ad605a474643f154db8313fc53c823f04 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:09:01 +0100 Subject: [PATCH 03/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 0dd4a4343..12266f78c 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -72,7 +72,7 @@ and now it works: [0.0, 0.0, 0.0, 0.0]]], shape=[3, 2, 4], strides=[1, 3, 6], layout=F (0x2), const ndim=3 ``` -We can also specify it's dimensionality +We can also specify its dimensionality ```rust use ndarray::prelude::*; From b1659a69601d9117afa832bc80e951f6a701f2e5 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:10:41 +0100 Subject: [PATCH 04/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 12266f78c..eae0e5df3 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -124,7 +124,7 @@ fn main() { } ``` -And try remove all the `&` sign in front of `a` and `b`, see if it still compiles. Why? +Try remove all the `&` sign in front of `a` and `b`, does it still compile? Why? Note that * `&A @ &A` which produces a new `Array` From 2160823d39ce702d438de820c142026df1adc6d9 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:11:07 +0100 Subject: [PATCH 05/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index eae0e5df3..f963fa80a 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -127,10 +127,10 @@ fn main() { Try remove all the `&` sign in front of `a` and `b`, does it still compile? Why? Note that -* `&A @ &A` which produces a new `Array` -* `B @ A` which consumes `B`, updates it with the result, and returns it -* `B @ &A` which consumes `B`, updates it with the result, and returns it -* `C @= &A` which performs an arithmetic operation in place +* `&A @ &A` produces a new `Array` +* `B @ A` consumes `B`, updates it with the result, and returns it +* `B @ &A` consumes `B`, updates it with the result, and returns it +* `C @= &A` performs an arithmetic operation in place More info checkout https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#arithmetic-operations From 807108edb2bbbb0942bdb02e9aa28dc2c9309880 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:11:47 +0100 Subject: [PATCH 06/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index f963fa80a..7b654b765 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -134,7 +134,7 @@ Note that More info checkout https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#arithmetic-operations -Some operations have `_axis` appended on the function name that can take in `Axis` as parameters, +Some operations have `_axis` appended to the function name: they generally take in a parameter of type `Axis` as one of their inputs, such as `sum_axis`: ```rust From e12a8a6c7a0ca854f85c1a53d48897aa1cfbe078 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:11:55 +0100 Subject: [PATCH 07/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 7b654b765..06d86e4e0 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -225,7 +225,7 @@ The output is: More info about iteration see [Loops, Producers, and Iterators](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#loops-producers-and-iterators) -Let's try a 3D array having element type as `isize`. This is how you can indexing +Let's try a 3D array with elements of type `isize`. This is how you index it: ```rust use ndarray::prelude::*; From e0b78c7abbc53be1911d5715721ecf092e87e573 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:16:53 +0100 Subject: [PATCH 08/14] Address PR input --- README-quick-start.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 2f9a7857c..ecf93e2cd 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -84,7 +84,7 @@ fn main() { ``` `Ix3` stands for 3D array. -And now we are type checked. Try change the above code to `Array::::zeros((3, 2, 4, 5).f());` +And now we are type checked. Try change the code above to `Array::::zeros((3, 2, 4, 5).f());` and compile, see what happens. ### Some common create helper functions @@ -525,6 +525,9 @@ b clone of a = [2, 3]] ``` +Noticing that `clone()` will perform a deep copy of the array elements only if you are cloning an owned array (i.e. `Array`). +Cloning an `ArrayView` does not clone the underlying elements - you are just cloning the view reference (as it happens in Rust when cloning a `&` reference). + ## Broadcasting Arrays support limited broadcasting, where arithmetic operations with array operands of different sizes can be carried out by repeating the elements of the smaller dimension array. From 1e3083e919252829d73fabe64733ab8c429d18d1 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:29:09 +0100 Subject: [PATCH 09/14] Add README ref --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index 3f5c87c91..f6f012047 100644 --- a/README.rst +++ b/README.rst @@ -5,6 +5,7 @@ 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 <./README-quick-start.md>`_. __ https://docs.rs/ndarray/ From 81b7c8aa4046d7827f8c53fd2ebb1fdf26d54373 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Wed, 25 Mar 2020 20:32:34 +0100 Subject: [PATCH 10/14] Update README-quick-start.md Co-Authored-By: Luca Palmieri --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 9aeb5cfa2..da7ddd90f 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -223,7 +223,7 @@ The output is: 9.999999999999998, 1, 9.999999999999998, 3, 9.999999999999998, 4.999999999999999, 5.999999999999999, 6.999999999999999, 7.999999999999999, 8.999999999999998, ``` -More info about iteration see [Loops, Producers, and Iterators](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#loops-producers-and-iterators) +For more info about iteration see [Loops, Producers, and Iterators](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#loops-producers-and-iterators) Let's try a 3D array with elements of type `isize`. This is how you index it: ```rust From 70e882632709fa496c5301e5c139f0b452fd4be4 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Sat, 11 Apr 2020 13:00:15 +0200 Subject: [PATCH 11/14] Add from_elm illustration --- README-quick-start.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/README-quick-start.md b/README-quick-start.md index da7ddd90f..1166938e1 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -87,6 +87,18 @@ fn main() { And now we are type checked. Try change the code above to `Array::::zeros((3, 2, 4, 5).f());` and compile, see what happens. +### How about create array of different type and having different initial values? + +The [`from_elm`](http://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.from_elem) method can be handy here: + +```rust +use ndarray::{Array, Ix3}; +fn main() { + let a = Array::::from_elem((3, 2, 4), false); + println!("{:?}", a); +} +``` + ### Some common create helper functions `linspace` - Create a 1-D array with 21 elements with values 0., …, 5. ```rust From 0f546059478783c2ffd9d69b07973661dc1b98e6 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Sat, 11 Apr 2020 13:08:05 +0200 Subject: [PATCH 12/14] Address PR input --- README-quick-start.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README-quick-start.md b/README-quick-start.md index 1166938e1..67dcaa047 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -144,7 +144,7 @@ Note that * `B @ &A` consumes `B`, updates it with the result, and returns it * `C @= &A` performs an arithmetic operation in place -More info checkout https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#arithmetic-operations +For more info checkout https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#arithmetic-operations Some operations have `_axis` appended to the function name: they generally take in a parameter of type `Axis` as one of their inputs, such as `sum_axis`: From a235c3532d77c859db9935043b1cb4b0e86bf0e1 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Mon, 20 Apr 2020 20:34:26 +0200 Subject: [PATCH 13/14] Address PR input --- README-quick-start.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index 67dcaa047..335b424bc 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -435,7 +435,7 @@ s2 = As in Rust we have owner ship, so we cannot simply update an element of an array while we have a shared view of it. This will help us write more -robust code than numpy. +robust code. ```rust use ndarray::prelude::*; @@ -537,7 +537,8 @@ b clone of a = [2, 3]] ``` -Noticing that `clone()` will perform a deep copy of the array elements only if you are cloning an owned array (i.e. `Array`). +Noticing that using `clone()` (or cloning) an `Array` type will also copies the array's elements, it creates an independently owned array of the same type. + Cloning an `ArrayView` does not clone the underlying elements - you are just cloning the view reference (as it happens in Rust when cloning a `&` reference). ## Broadcasting @@ -602,4 +603,4 @@ a is broadcased to 3x2x2 = ## Want to learn more? Please checkout these docs for more information * [`ArrayBase` doc page](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html) -* [`ndarray` for `numpy` user doc page](https://docs.rs/ndarray/0.13.0/ndarray/doc/ndarray_for_numpy_users/index.html) +* [`ndarray` for `numpy` user doc page](https://docs.rs/ndarray/latest/ndarray/doc/ndarray_for_numpy_users/index.html) From 74252bea889cc48c261bd0452be73b3a6dcd5b37 Mon Sep 17 00:00:00 2001 From: Fuyang Liu Date: Mon, 20 Apr 2020 20:38:08 +0200 Subject: [PATCH 14/14] Minor fix up --- README-quick-start.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README-quick-start.md b/README-quick-start.md index 335b424bc..2adc04d70 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -537,9 +537,9 @@ b clone of a = [2, 3]] ``` -Noticing that using `clone()` (or cloning) an `Array` type will also copies the array's elements, it creates an independently owned array of the same type. +Noticing that using `clone()` (or cloning) an `Array` type also copies the array's elements. It creates an independently owned array of the same type. -Cloning an `ArrayView` does not clone the underlying elements - you are just cloning the view reference (as it happens in Rust when cloning a `&` reference). +Cloning an `ArrayView` does not clone or copy the underlying elements - it just clones the view reference (as it happens in Rust when cloning a `&` reference). ## Broadcasting