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"
mime = "0.3"
nalgebra = "0.16.12"
ndarray = "0.12"
ndarray = { version = "0.13", features = ["approx"] }
num = "0.2"
num_cpus = "1.8"
percent-encoding = "2.1"

View file

@ -1,10 +1,10 @@
# Linear Algebra
{{#include linear_algebra/vector-sum.md}}
{{#include linear_algebra/vector-norm.md}}
{{#include linear_algebra/add-matrices.md}}
{{#include linear_algebra/multiply-matrices.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 ../../links.md}}

View file

@ -1,7 +1,9 @@
## Adding matrices
[![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
extern crate ndarray;
@ -15,7 +17,13 @@ fn main() {
let b = arr2(&[[6, 5, 4],
[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]
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
[`ndarray::Array2::dot`]. (`dot` performs matrix multiplication, while the `*`
operator performs element-wise multiplication.) In `ndarray`, 1-D arrays can be
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
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.
[`ndarray::Array2::dot`]. (Matrix multiplication is performed using `dot`, while
the `*` operator performs element-wise multiplication.)
In `ndarray`, 1-D arrays can be 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 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
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::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]
This recipe demonstrates use of the [`Array1`] type, [`ArrayView1`] type,
[`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
square root of the dot product of a vector with itself, shown in the function
`l2_norm`. The l1 norm, shown in the function `l1_norm`, is computed by a `fold`
given vector.
+ The `l2_norm` function is the simpler of the two, as it computes the
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
performed with `x.mapv(f64::abs).scalar_sum()`, but that would allocate a new
array for the result of the `mapv`.)
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
dimensional views (hence [`ArrayView1`]). While the functions could take a
considers vector norms, so the norm functions only need to accept one-dimensional
views (hence [`ArrayView1`]). While the functions could take a
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
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
`&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,
that may be a better choice for the benefit of your users, but for internal
functions, the more concise `ArrayView1<f64>` may be preferable.
array).
`Array` and `ArrayView` are both type aliases for `ArrayBase`. So, the most
general argument type for the caller would be `&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 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
#[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
[`ArrayView1`]: https://docs.rs/ndarray/*/ndarray/type.ArrayView1.html
[`dot`]: https://docs.rs/ndarray/*/ndarray/struct.ArrayBase.html#method.dot
[`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