Update to ndarray 0.13 (#560)

This commit is contained in:
Dan Wilhelm 2019-12-16 18:13:33 -08:00 committed by Andrew Gauger
parent 3fcb08bee2
commit d7c291151f
7 changed files with 92 additions and 77 deletions

View file

@ -29,7 +29,7 @@ log4rs = "0.8"
memmap = "0.7" memmap = "0.7"
mime = "0.3" mime = "0.3"
nalgebra = "0.16.12" nalgebra = "0.16.12"
ndarray = "0.12" ndarray = { version = "0.13", features = ["approx"] }
num = "0.2" num = "0.2"
num_cpus = "1.8" num_cpus = "1.8"
percent-encoding = "2.1" percent-encoding = "2.1"

View file

@ -1,10 +1,10 @@
# Linear Algebra # Linear Algebra
{{#include linear_algebra/vector-sum.md}}
{{#include linear_algebra/vector-norm.md}}
{{#include linear_algebra/add-matrices.md}} {{#include linear_algebra/add-matrices.md}}
{{#include linear_algebra/multiply-matrices.md}} {{#include linear_algebra/multiply-matrices.md}}
{{#include linear_algebra/multiply-scalar-vector-matrix.md}} {{#include linear_algebra/multiply-scalar-vector-matrix.md}}
{{#include linear_algebra/vector-comparison.md}}
{{#include linear_algebra/vector-norm.md}}
{{#include linear_algebra/invert-matrix.md}} {{#include linear_algebra/invert-matrix.md}}
{{#include ../../links.md}} {{#include ../../links.md}}

View file

@ -1,7 +1,9 @@
## Adding matrices ## Adding matrices
[![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science] [![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science]
Creates two matrices with [`ndarray::arr2`] and adds them together. Creates two 2-D matrices with [`ndarray::arr2`] and sums them element-wise.
Note the sum is computed as `let sum = &a + &b`. The `&` operator is used to avoid consuming `a` and `b`, making them available later for display. A new array is created containing their sum.
```rust ```rust
extern crate ndarray; extern crate ndarray;
@ -15,7 +17,13 @@ fn main() {
let b = arr2(&[[6, 5, 4], let b = arr2(&[[6, 5, 4],
[3, 2, 1]]); [3, 2, 1]]);
println!("Sum: {}", a + b); let sum = &a + &b;
println!("{}", a);
println!("+");
println!("{}", b);
println!("=");
println!("{}", sum);
} }
``` ```

View file

@ -2,14 +2,18 @@
[![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science] [![ndarray-badge]][ndarray] [![cat-science-badge]][cat-science]
Creates a 1-D array (vector) with [`ndarray::arr1`] and a 2-D array (matrix) Creates a 1-D array (vector) with [`ndarray::arr1`] and a 2-D array (matrix)
with [`ndarray::arr2`]. First, a scalar is multiplied by the vector to get with [`ndarray::arr2`].
First, a scalar is multiplied by the vector to get
another vector. Then, the matrix is multiplied by the new vector with another vector. Then, the matrix is multiplied by the new vector with
[`ndarray::Array2::dot`]. (`dot` performs matrix multiplication, while the `*` [`ndarray::Array2::dot`]. (Matrix multiplication is performed using `dot`, while
operator performs element-wise multiplication.) In `ndarray`, 1-D arrays can be the `*` operator performs element-wise multiplication.)
interpreted as either row or column vectors depending on context. If
representing the orientation of a vector is important, a 2-D array with one row In `ndarray`, 1-D arrays can be interpreted as either row or column vectors
or one column must be used instead. In this example, the vector is a 1-D array depending on context. If representing the orientation of a vector is important,
on the right-hand side, so `dot` handles it as a column vector. a 2-D array with one row or one column must be used instead. In this example,
the vector is a 1-D array on the right-hand side, so `dot` handles it as a column
vector.
```rust ```rust
extern crate ndarray; extern crate ndarray;
@ -32,6 +36,6 @@ fn main() {
} }
``` ```
[`ndarray::Array2::dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1
[`ndarray::arr1`]: https://docs.rs/ndarray/*/ndarray/fn.arr1.html [`ndarray::arr1`]: https://docs.rs/ndarray/*/ndarray/fn.arr1.html
[`ndarray::arr2`]: https://docs.rs/ndarray/*/ndarray/fn.arr2.html [`ndarray::arr2`]: https://docs.rs/ndarray/*/ndarray/fn.arr2.html
[`ndarray::Array2::dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot-1

View file

@ -0,0 +1,50 @@
## Vector comparison
[![ndarray-badge]][ndarray]
The [ndarray] crate supports a number of ways to create arrays -- this recipe creates
[`ndarray::Array`]s from `std::Vec` using `from`. Then, it sums the arrays element-wise.
This recipe contains an example of comparing two floating-point vectors element-wise.
Floating-point numbers are often stored inexactly, making exact comparisons difficult.
However, the [`assert_abs_diff_eq!`] macro from the [`approx`] crate allows for convenient
element-wise comparisons. To use the `approx` crate with `ndarray`, the `approx`
feature must be added to the `ndarray` dependency in `Cargo.toml`. For example,
`ndarray = { version = "0.13", features = ["approx"] }`.
This recipe also contains additional ownership examples. Here, `let z = a + b` consumes
`a` and `b`, updates `a` with the result, then moves ownership to `z`. Alternatively,
`let w = &c + &d` creates a new vector without consuming `c` or `d`, allowing
their modification later. See [Binary Operators With Two Arrays] for additional detail.
```rust
#[macro_use(assert_abs_diff_eq)]
extern crate approx;
extern crate ndarray;
use ndarray::Array;
fn main() {
let a = Array::from(vec![1., 2., 3., 4., 5.]);
let b = Array::from(vec![5., 4., 3., 2., 1.]);
let mut c = Array::from(vec![1., 2., 3., 4., 5.]);
let mut d = Array::from(vec![5., 4., 3., 2., 1.]);
let z = a + b;
let w = &c + &d;
assert_abs_diff_eq!(z, Array::from(vec![6., 6., 6., 6., 6.]));
println!("c = {}", c);
c[0] = 10.;
d[1] = 10.;
assert_abs_diff_eq!(w, Array::from(vec![6., 6., 6., 6., 6.]));
}
```
[`approx`]: https://docs.rs/approx/*/approx/index.html
[`assert_abs_diff_eq!`]: https://docs.rs/approx/*/approx/macro.assert_abs_diff_eq.html
[Binary Operators With Two Arrays]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays
[ndarray]: https://docs.rs/crate/ndarray/*
[`ndarray::Array`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html

View file

@ -1,26 +1,30 @@
## Vector Norm ## Vector norm
[![ndarray-badge]][ndarray] [![ndarray-badge]][ndarray]
This recipe demonstrates use of the [`Array1`] type, [`ArrayView1`] type, This recipe demonstrates use of the [`Array1`] type, [`ArrayView1`] type,
[`fold`] method, and [`dot`] method in computing the [l1] and [l2] norms of a [`fold`] method, and [`dot`] method in computing the [l1] and [l2] norms of a
given vector. The l2 norm calculation is the simpler of the two, as it is the given vector.
square root of the dot product of a vector with itself, shown in the function + The `l2_norm` function is the simpler of the two, as it computes the
`l2_norm`. The l1 norm, shown in the function `l1_norm`, is computed by a `fold` square root of the dot product of a vector with itself.
+ The `l1_norm` function is computed by a `fold`
operation that sums the absolute values of the elements. (This could also be operation that sums the absolute values of the elements. (This could also be
performed with `x.mapv(f64::abs).scalar_sum()`, but that would allocate a new performed with `x.mapv(f64::abs).scalar_sum()`, but that would allocate a new
array for the result of the `mapv`.) array for the result of the `mapv`.)
Note that both `l1_norm` and `l2_norm` take the [`ArrayView1`] type. This recipe Note that both `l1_norm` and `l2_norm` take the [`ArrayView1`] type. This recipe
considers vector norms, so the norm functions only need to accept one considers vector norms, so the norm functions only need to accept one-dimensional
dimensional views (hence [`ArrayView1`]). While the functions could take a views (hence [`ArrayView1`]). While the functions could take a
parameter of type `&Array1<f64>` instead, that would require the caller to have parameter of type `&Array1<f64>` instead, that would require the caller to have
a reference to an owned array, which is more restrictive than just having access a reference to an owned array, which is more restrictive than just having access
to a view (since a view can be created from any array or view, not just an owned to a view (since a view can be created from any array or view, not just an owned
array). The most convenient argument type for the caller would be array).
`&ArrayBase<S, Ix1> where S: Data`, because then the caller could use `&array`
or `&view` instead of `x.view()`. If the function is part of your public API, `Array` and `ArrayView` are both type aliases for `ArrayBase`. So, the most
that may be a better choice for the benefit of your users, but for internal general argument type for the caller would be `&ArrayBase<S, Ix1> where S: Data`,
functions, the more concise `ArrayView1<f64>` may be preferable. because then the caller could use `&array` or `&view` instead of `x.view()`.
If the function is part of a public API, that may be a better choice for the
benefit of users. For internal functions, the more concise `ArrayView1<f64>`
may be preferable.
```rust ```rust
#[macro_use(array)] #[macro_use(array)]
@ -50,9 +54,9 @@ fn main() {
} }
``` ```
[l1]: http://mathworld.wolfram.com/L1-Norm.html
[l2]: http://mathworld.wolfram.com/L2-Norm.html
[`Array1`]: https://docs.rs/ndarray/*/ndarray/type.Array1.html [`Array1`]: https://docs.rs/ndarray/*/ndarray/type.Array1.html
[`ArrayView1`]: https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html [`ArrayView1`]: https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html
[`dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot [`dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot
[`fold`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.fold [`fold`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.fold
[l1]: http://mathworld.wolfram.com/L1-Norm.html
[l2]: http://mathworld.wolfram.com/L2-Norm.html

View file

@ -1,51 +0,0 @@
## Vector Sum
[![ndarray-badge]][ndarray]
The [ndarray] crate supports a number of ways to create arrays -- this recipe
focuses on creating [`ndarray::Array`]s from `std::Vec` via [`from_vec`]. Adding two
arrays together is no different than adding two numbers together. Using the `&`
operand on the arrays within an arithmetic operation prevents the operation from
consuming the arrays. Without `&`, the arrays are consumed.
In the first example, arrays `a` and `b` are moved in the let-statement `z = a +
b`. In the second example, the arrays `c` and `d` are not moved and instead, a
new array is created for `w`. Updating either of `c` or `d` after the vector sum
has no effect the value of `w`. Additionally, while printing `c` works as
expected, it would be an error to print `b` due to the move. See [Binary
Operators With Two Arrays] for additional detail.
```rust
extern crate ndarray;
use ndarray::Array;
fn main() {
let a = Array::from_vec(vec![1., 2., 3., 4., 5.]);
let b = Array::from_vec(vec![5., 4., 3., 2., 1.]);
let mut c = Array::from_vec(vec![1., 2., 3., 4., 5.]);
let mut d = Array::from_vec(vec![5., 4., 3., 2., 1.]);
let z = a + b;
let w = &c + &d;
let epsilon = 1e-8;
for elem in z.iter() {
let diff: f32 = *elem - 6.;
assert!(diff.abs() < epsilon);
}
println!("c = {}", c);
c[0] = 10.;
d[1] = 10.;
for elem in w.iter() {
let diff: f32 = *elem - 6.;
assert!(diff.abs() < epsilon);
}
}
```
[Binary Operators With Two Arrays]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#binary-operators-with-two-arrays
[`from_vec`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.from_vec
[ndarray]: https://docs.rs/crate/ndarray/*
[`ndarray::Array`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html