diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 35f72acf4..7dfc3bdc1 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -1,6 +1,11 @@ on: + push: + branches: + - "**" pull_request: merge_group: + workflow_dispatch: + workflow_call: name: Continuous integration @@ -8,12 +13,13 @@ env: CARGO_TERM_COLOR: always HOST: x86_64-unknown-linux-gnu FEATURES: "test docs" - RUSTFLAGS: "-D warnings" + # RUSTFLAGS: "-D warnings" # For now, we don't mind a couple warnings jobs: clippy: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: rust: - beta @@ -30,6 +36,7 @@ jobs: format: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: rust: - nightly @@ -45,12 +52,13 @@ jobs: tests: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: rust: - stable - beta - nightly - - 1.57.0 # MSRV + - 1.63.0 # MSRV name: tests/${{ matrix.rust }} steps: @@ -67,6 +75,7 @@ jobs: if: ${{ github.event_name == 'merge_group' }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: include: - rust: stable @@ -90,6 +99,8 @@ jobs: if: ${{ github.event_name == 'merge_group' }} runs-on: ubuntu-latest name: cargo-careful + strategy: + fail-fast: false steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@master @@ -105,6 +116,7 @@ jobs: if: ${{ github.event_name == 'merge_group' }} runs-on: ubuntu-latest strategy: + fail-fast: false matrix: rust: - stable @@ -125,6 +137,8 @@ jobs: - cargo-careful - docs if: always() + strategy: + fail-fast: false runs-on: ubuntu-latest steps: - name: Result diff --git a/.gitignore b/.gitignore index 1e7caa9ea..ffb44634d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ Cargo.lock target/ + +.DS_Store diff --git a/Cargo.toml b/Cargo.toml index ae9e33f06..ed35fc83a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,10 +3,11 @@ name = "ndarray" version = "0.15.6" edition = "2018" -rust-version = "1.57" +rust-version = "1.63" authors = [ - "Ulrik Sverdrup \"bluss\"", - "Jim Turner" + "Ulrik Sverdrup \"bluss\"", + "Jim Turner", + "Toby Davis \"Pencilcaseman\"", ] license = "MIT OR Apache-2.0" readme = "README-crates.io.md" @@ -31,33 +32,46 @@ num-integer = { version = "0.1.39", default-features = false } num-traits = { version = "0.2", default-features = false } num-complex = { version = "0.4", default-features = false } +# Use via the `opencl` crate feature! +hasty_ = { version = "0.2", optional = true, package = "hasty", default-features = false } +#hasty_ = { path = "../../hasty_dev/hasty", optional = true, package = "hasty", default-features = false } +#once_cell_ = { version = "1.19", optional = true, package = "once_cell" } + # Use via the `rayon` crate feature! rayon_ = { version = "1.0.3", optional = true, package = "rayon" } -approx = { version = "0.4", optional = true , default-features = false } -approx-0_5 = { package = "approx", version = "0.5", optional = true , default-features = false } +approx = { version = "0.4", optional = true, default-features = false } +approx-0_5 = { package = "approx", version = "0.5", optional = true, default-features = false } # Use via the `blas` crate feature! cblas-sys = { version = "0.1.4", optional = true, default-features = false } libc = { version = "0.2.82", optional = true } -matrixmultiply = { version = "0.3.2", default-features = false, features=["cgemm"] } +matrixmultiply = { version = "0.3.2", default-features = false, features = [ + "cgemm", +] } -serde = { version = "1.0", optional = true, default-features = false, features = ["alloc"] } +serde = { version = "1.0", optional = true, default-features = false, features = [ + "alloc", +] } rawpointer = { version = "0.2" } [dev-dependencies] defmac = "0.2" quickcheck = { version = "1.0", default-features = false } approx = "0.4" -itertools = { version = "0.10.0", default-features = false, features = ["use_std"] } +itertools = { version = "0.12", default-features = false, features = ["use_std"] } [features] default = ["std"] +# Enable OpenCL backend +opencl = ["hasty_/opencl"] +cuda = ["hasty_/cuda"] + # Enable blas usage # See README for more instructions -blas = ["cblas-sys", "libc"] +blas = ["cblas-sys", "libc", "hasty_/blas"] # Old name for the serde feature serde-1 = ["serde"] @@ -75,8 +89,10 @@ matrixmultiply-threading = ["matrixmultiply/threading"] [profile.bench] debug = true + [profile.dev.package.numeric-tests] opt-level = 2 + [profile.test.package.numeric-tests] opt-level = 2 diff --git a/README-crates.io.md b/README-crates.io.md index 3c6b09054..79e6cd521 100644 --- a/README-crates.io.md +++ b/README-crates.io.md @@ -1,4 +1,3 @@ - `ndarray` implements an *n*-dimensional container for general elements and for numerics. diff --git a/README-quick-start.md b/README-quick-start.md index ad13acc72..693386169 100644 --- a/README-quick-start.md +++ b/README-quick-start.md @@ -1,13 +1,15 @@ # 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. +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/) to immediately try out the examples. ## The Basics -You can create your first 2x3 floating-point ndarray as such: +You can create your first 2x3 floating-point ndarray as such: + ```rust use ndarray::prelude::*; @@ -24,7 +26,9 @@ fn main() { println!("{:?}", a); } ``` + This code will create a simple array, then print it to stdout as such: + ``` [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]], shape=[2, 3], strides=[3, 1], layout=C (0x1), const ndim=2 @@ -34,7 +38,9 @@ This code will create a simple array, then print it to stdout as such: ### Element type and dimensionality -Now let's create more arrays. A common operation on matrices is to create a matrix full of 0's of certain dimensions. Let's try to do that with dimensions (3, 2, 4) using the `Array::zeros` function: +Now let's create more arrays. A common operation on matrices is to create a matrix full of 0's of certain dimensions. +Let's try to do that with dimensions (3, 2, 4) using the `Array::zeros` function: + ```rust use ndarray::prelude::*; use ndarray::Array; @@ -43,13 +49,17 @@ fn main() { println!("{:?}", a); } ``` + Unfortunately, this code does not compile. + ``` | let a = Array::zeros((3, 2, 4).f()); | - ^^^^^^^^^^^^ cannot infer type for type parameter `A` ``` -Indeed, note that the compiler needs to infer the element type and dimensionality from context only. In this -case the compiler does not have enough information. To fix the code, we can explicitly give the element type through turbofish syntax, and let it infer the dimensionality type: + +Indeed, note that the compiler needs to infer the element type and dimensionality from context only. In this +case the compiler does not have enough information. To fix the code, we can explicitly give the element type through +turbofish syntax, and let it infer the dimensionality type: ```rust use ndarray::prelude::*; @@ -59,7 +69,9 @@ fn main() { println!("{:?}", a); } ``` + This code now compiles to what we wanted: + ``` [[[0.0, 0.0, 0.0, 0.0], [0.0, 0.0, 0.0, 0.0]], @@ -71,11 +83,15 @@ This code now compiles to what we wanted: [0.0, 0.0, 0.0, 0.0]]], shape=[3, 2, 4], strides=[1, 3, 6], layout=F (0x2), const ndim=3 ``` -We could also specify its dimensionality explicitly `Array::::zeros(...)`, with`Ix3` standing for 3D array type. Phew! We achieved type safety. If you tried changing the code above to `Array::::zeros((3, 2, 4, 5).f());`, which is not of dimension 3 anymore, Rust's type system would gracefully prevent you from compiling the code. +We could also specify its dimensionality explicitly `Array::::zeros(...)`, with`Ix3` standing for 3D array +type. Phew! We achieved type safety. If you tried changing the code above +to `Array::::zeros((3, 2, 4, 5).f());`, which is not of dimension 3 anymore, Rust's type system would +gracefully prevent you from compiling the code. ### Creating arrays with different initial values and/or different types -The [`from_elem`](http://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.from_elem) method allows initializing an array of given dimension to a specific value of any type: +The [`from_elem`](http://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.from_elem) method allows +initializing an array of given dimension to a specific value of any type: ```rust use ndarray::{Array, Ix3}; @@ -86,7 +102,9 @@ fn main() { ``` ### Some common array initializing helper functions + `linspace` - Create a 1-D array with 11 elements with values 0., …, 5. + ```rust use ndarray::prelude::*; use ndarray::{Array, Ix3}; @@ -95,16 +113,21 @@ fn main() { 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 ``` -Common array initializing methods include [`range`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.range), [`logspace`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.logspace), [`eye`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.eye), [`ones`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.ones)... +Common array initializing methods +include [`range`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.range), [`logspace`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.logspace), [`eye`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.eye), [`ones`](https://docs.rs/ndarray/0.13.0/ndarray/struct.ArrayBase.html#method.ones)... ## Basic operations -Basic operations on arrays are all element-wise; you need to use specific methods for operations such as matrix multiplication (see later section). +Basic operations on arrays are all element-wise; you need to use specific methods for operations such as matrix +multiplication (see later section). + ```rust use ndarray::prelude::*; use ndarray::Array; @@ -123,20 +146,20 @@ fn main() { } ``` - Note that (for any binary operator `@`): + * `&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 -Try removing all the `&` sign in front of `a` and `b` in the last example: it will not compile anymore because of those rules. +Try removing all the `&` sign in front of `a` and `b` in the last example: it will not compile anymore because of those +rules. 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, +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 @@ -176,7 +199,9 @@ fn main() { println!("{}", a.t().dot(&b.t())); // [4, 1] x [1, 4] -> [4, 4] } ``` + The output is: + ``` a shape [1, 4] b shape [4] @@ -189,6 +214,7 @@ b shape after reshape [4, 1] ``` ## Indexing, Slicing and Iterating + One-dimensional arrays can be indexed, sliced and iterated over, much like `numpy` arrays ```rust @@ -215,7 +241,9 @@ fn main() { } } ``` + The output is: + ``` [0, 1, 8, 27, 64, 125, 216, 343, 512, 729] 8 @@ -225,9 +253,11 @@ The output is: 9.999999999999998, 1, 9.999999999999998, 3, 9.999999999999998, 4.999999999999999, 5.999999999999999, 6.999999999999999, 7.999999999999999, 8.999999999999998, ``` -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) +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 iterating over a 3D array with elements of type `isize`. This is how you index it: -Let's try a iterating over a 3D array with elements of type `isize`. This is how you index it: ```rust use ndarray::prelude::*; @@ -261,7 +291,9 @@ fn main() { } } ``` + The output is: + ``` a -> [[[0, 1, 2], @@ -295,6 +327,7 @@ row: [[100, 101, 102], ## Shape Manipulation ### Changing the shape of an array + The shape of an array can be changed with the `into_shape_with_order` or `to_shape` method. ````rust @@ -323,7 +356,9 @@ fn main() { println!("c = \n{:?}", c); } ```` + The output is: + ``` a = [[3.0, 7.0, 3.0, 4.0], @@ -370,7 +405,9 @@ fn main() { println!("concatenate, axis 1:\n{:?}\n", concatenate![Axis(1), a, b]); } ``` + The output is: + ``` stack, axis 0: [[[3.0, 7.0, 8.0], @@ -409,6 +446,7 @@ concatenate, axis 1: ### 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; @@ -431,7 +469,9 @@ fn main() { println!("s2 = \n{}\n", s2); } ``` + The output is: + ``` Split a from Axis(0), at index 1: s1 = @@ -450,9 +490,12 @@ s2 = ``` ## Copies and Views + ### View, Ref or Shallow Copy -Rust has ownership, so we cannot simply update an element of an array while we have a shared view of it. This brings guarantees & helps having more robust code. +Rust has ownership, so we cannot simply update an element of an array while we have a shared view of it. This brings +guarantees & helps having more robust code. + ```rust use ndarray::prelude::*; use ndarray::{Array, Axis}; @@ -482,7 +525,9 @@ fn main() { println!("s2 = \n{}\n", s2); } ``` + The output is: + ``` a = [[0, 1, 2, 3], @@ -511,8 +556,10 @@ s2 = ``` ### 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; @@ -534,6 +581,7 @@ fn main() { ``` The output is: + ``` a = [[0, 1], @@ -553,13 +601,16 @@ b clone of a = [2, 3]] ``` -Notice that using `clone()` (or cloning) an `Array` type also copies the array's elements. It creates an independently owned array of the same type. +Notice 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 or copy the underlying elements - it only clones the view reference (as it happens in Rust when cloning a `&` reference). +Cloning an `ArrayView` does not clone or copy the underlying elements - it only clones 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. +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::*; @@ -585,9 +636,11 @@ fn main() { } ``` -See [.broadcast()](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.broadcast) for a more detailed description. +See [.broadcast()](https://docs.rs/ndarray/latest/ndarray/struct.ArrayBase.html#method.broadcast) for a more detailed +description. And here is a short example of it: + ```rust use ndarray::prelude::*; @@ -602,7 +655,9 @@ fn main() { println!("a is broadcased to 3x2x2 = \n{}", b); } ``` + The output is: + ``` shape of a is [2, 2] a is broadcased to 3x2x2 = @@ -617,6 +672,8 @@ 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/latest/ndarray/doc/ndarray_for_numpy_users/index.html) diff --git a/RELEASES.md b/RELEASES.md index 364166718..07de2436f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -26,7 +26,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/1191 - Version 0.15.5 (2022-07-30) =========================== @@ -45,7 +44,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/1134
https://github.com/rust-ndarray/ndarray/pull/1164 - Version 0.15.4 (2021-11-23) =========================== @@ -164,7 +162,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/1114 - Version 0.15.3 (2021-06-05) =========================== @@ -215,7 +212,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/1009 - Version 0.15.2 (2021-05-17 🇳🇴) ================================ @@ -225,8 +221,8 @@ New features - New methods for growing/appending to owned `Array`s. These methods allow building an array efficiently chunk by chunk. By [@bluss]. - - `.push_row()`, `.push_column()` - - `.push(axis, array)`, `.append(axis, array)` + - `.push_row()`, `.push_column()` + - `.push(axis, array)`, `.append(axis, array)` `stack`, `concatenate` and `.select()` now support all `Clone`-able elements as a result. @@ -306,7 +302,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/1004 - Version 0.15.1 (2021-03-29) =========================== @@ -334,7 +329,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/955
https://github.com/rust-ndarray/ndarray/pull/959 - Version 0.15.0 (2021-03-25) =========================== @@ -436,22 +430,22 @@ API changes - Changes to the slicing-related types and macro by [@jturner314] and [@bluss]: - - Remove the `Dimension::SliceArg` associated type, and add a new `SliceArg` - trait for this purpose. - - Change the return type of the `s![]` macro to an owned `SliceInfo` rather - than a reference. - - Replace the `SliceOrIndex` enum with `SliceInfoElem`, which has an - additional `NewAxis` variant and does not have a `step_by` method. - - Change the type parameters of `SliceInfo` in order to support the `NewAxis` - functionality and remove some tricky `unsafe` code. - - Mark the `SliceInfo::new` method as `unsafe`. The new implementations of - `TryFrom` can be used as a safe alternative. - - Remove the `AsRef> for SliceInfo` - implementation. Add the similar `From<&'a SliceInfo> for - SliceInfo<&'a [SliceInfoElem], Din, Dout>` conversion as an alternative. - - Change the *expr* `;` *step* case in the `s![]` macro to error at compile - time if an unsupported type for *expr* is used, instead of panicking at - runtime. + - Remove the `Dimension::SliceArg` associated type, and add a new `SliceArg` + trait for this purpose. + - Change the return type of the `s![]` macro to an owned `SliceInfo` rather + than a reference. + - Replace the `SliceOrIndex` enum with `SliceInfoElem`, which has an + additional `NewAxis` variant and does not have a `step_by` method. + - Change the type parameters of `SliceInfo` in order to support the `NewAxis` + functionality and remove some tricky `unsafe` code. + - Mark the `SliceInfo::new` method as `unsafe`. The new implementations of + `TryFrom` can be used as a safe alternative. + - Remove the `AsRef> for SliceInfo` + implementation. Add the similar `From<&'a SliceInfo> for + SliceInfo<&'a [SliceInfoElem], Din, Dout>` conversion as an alternative. + - Change the *expr* `;` *step* case in the `s![]` macro to error at compile + time if an unsupported type for *expr* is used, instead of panicking at + runtime. https://github.com/rust-ndarray/ndarray/pull/570
https://github.com/rust-ndarray/ndarray/pull/940
@@ -460,10 +454,10 @@ API changes - Removed already deprecated methods by [@bluss]: - - Remove deprecated `.all_close()` - use approx feature and methods like `.abs_diff_eq` instead - - Mark `.scalar_sum()` as deprecated - use `.sum()` instead - - Remove deprecated `DataClone` - use `Data + RawDataClone` instead - - Remove deprecated `ArrayView::into_slice` - use `to_slice()` instead. + - Remove deprecated `.all_close()` - use approx feature and methods like `.abs_diff_eq` instead + - Mark `.scalar_sum()` as deprecated - use `.sum()` instead + - Remove deprecated `DataClone` - use `Data + RawDataClone` instead + - Remove deprecated `ArrayView::into_slice` - use `to_slice()` instead. https://github.com/rust-ndarray/ndarray/pull/874 @@ -474,10 +468,10 @@ API changes - Renamed `Zip` methods by [@bluss] and [@SparrowLii]: - - `apply` -> `for_each` - - `apply_collect` -> `map_collect` - - `apply_collect_into` -> `map_collect_into` - - (`par_` prefixed methods renamed accordingly) + - `apply` -> `for_each` + - `apply_collect` -> `map_collect` + - `apply_collect_into` -> `map_collect_into` + - (`par_` prefixed methods renamed accordingly) https://github.com/rust-ndarray/ndarray/pull/894
https://github.com/rust-ndarray/ndarray/pull/904
@@ -492,10 +486,10 @@ API changes - Renamed methods (old names are now deprecated) by [@bluss] and [@jturner314] - - `genrows/_mut` -> `rows/_mut` - - `gencolumns/_mut` -> `columns/_mut` - - `stack_new_axis` -> `stack` (the new name already existed) - - `visit` -> `for_each` + - `genrows/_mut` -> `rows/_mut` + - `gencolumns/_mut` -> `columns/_mut` + - `stack_new_axis` -> `stack` (the new name already existed) + - `visit` -> `for_each` https://github.com/rust-ndarray/ndarray/pull/872
https://github.com/rust-ndarray/ndarray/pull/937
@@ -506,7 +500,7 @@ API changes https://github.com/rust-ndarray/ndarray/pull/888
https://github.com/rust-ndarray/ndarray/pull/938
- + - Updated `num-complex` dependency to 0.4.0 by [@bluss] https://github.com/rust-ndarray/ndarray/pull/952 @@ -574,7 +568,6 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/887 - Version 0.14.0 (2020-11-28) =========================== @@ -606,7 +599,7 @@ API changes - The **old function** `stack` has been renamed to `concatenate`. A new function `stack` with numpy-like semantics have taken its place. Old usages of `stack` should change to use `concatenate`. - + `concatenate` produces an array with the same number of axes as the inputs. `stack` produces an array that has one more axis than the inputs. @@ -620,24 +613,23 @@ API changes - Remove deprecated items: - - RcArray (deprecated alias for ArcArray) - - Removed `subview_inplace` use `collapse_axis` - - Removed `subview_mut` use `index_axis_mut` - - Removed `into_subview` use `index_axis_move` - - Removed `subview` use `index_axis` - - Removed `slice_inplace` use `slice_collapse` + - RcArray (deprecated alias for ArcArray) + - Removed `subview_inplace` use `collapse_axis` + - Removed `subview_mut` use `index_axis_mut` + - Removed `into_subview` use `index_axis_move` + - Removed `subview` use `index_axis` + - Removed `slice_inplace` use `slice_collapse` - Undeprecated `remove_axis` because its replacement is hard to find out on your own. - Update public external dependencies to new versions by [@Eijebong] and [@bluss] - - num-complex 0.3 - - approx 0.4 (optional) - - blas-src 0.6.1 and openblas-src 0.9.0 (optional) + - num-complex 0.3 + - approx 0.4 (optional) + - blas-src 0.6.1 and openblas-src 0.9.0 (optional) https://github.com/rust-ndarray/ndarray/pull/810 - https://github.com/rust-ndarray/ndarray/pull/851 - + https://github.com/rust-ndarray/ndarray/pull/851 Other changes ------------- @@ -703,203 +695,205 @@ Other changes https://github.com/rust-ndarray/ndarray/pull/802 - Release management by [@bluss] - Version 0.13.0 (2019-09-23) =========================== New features ------------ - - `ndarray-parallel` is merged into `ndarray`. Use the `rayon` feature-flag to get access to parallel iterators and - other parallelized methods. - ([#563](https://github.com/rust-ndarray/ndarray/pull/563/files) by [@bluss]) - - Add `logspace` and `geomspace` constructors - ([#617](https://github.com/rust-ndarray/ndarray/pull/617) by [@JP-Ellis]) - - Implement approx traits for `ArrayBase`. They can be enabled using the `approx` feature-flag. - ([#581](https://github.com/rust-ndarray/ndarray/pull/581) by [@jturner314]) - - Add `mean` method - ([#580](https://github.com/rust-ndarray/ndarray/pull/580) by [@LukeMathWalker]) - - Add `Zip::all` to check if all elements satisfy a predicate - ([#615](https://github.com/rust-ndarray/ndarray/pull/615) by [@mneumann]) - - Add `RawArrayView` and `RawArrayViewMut` types and `RawData`, `RawDataMut`, and `RawDataClone` traits - ([#496](https://github.com/rust-ndarray/ndarray/pull/496) by [@jturner314]) - - Add `CowArray`, `C`lone `o`n `write` array - ([#632](https://github.com/rust-ndarray/ndarray/pull/632) by [@jturner314] and [@andrei-papou]) - - Add `as_standard_layout` to `ArrayBase`: it takes an array by reference and returns a `CoWArray` in standard layout - ([#616](https://github.com/rust-ndarray/ndarray/pull/616) by [@jturner314] and [@andrei-papou]) - - Add `Array2::from_diag` method to create 2D arrays from a diagonal - ([#673](https://github.com/rust-ndarray/ndarray/pull/673) by [@rth]) - - Add `fold` method to `Zip` - ([#684](https://github.com/rust-ndarray/ndarray/pull/684) by [@jturner314]) - - Add `split_at` method to `AxisChunksIter/Mut` - ([#691](https://github.com/rust-ndarray/ndarray/pull/691) by [@jturner314]) - - Implement parallel iteration for `AxisChunksIter/Mut` - ([#639](https://github.com/rust-ndarray/ndarray/pull/639) by [@nitsky]) - - Add `into_scalar` method to `ArrayView0` and `ArrayViewMut0` - ([#700](https://github.com/rust-ndarray/ndarray/pull/700) by [@LukeMathWalker]) - - Add `accumulate_axis_inplace` method to `ArrayBase` - ([#611](https://github.com/rust-ndarray/ndarray/pull/611) by [@jturner314] and [@bluss]) - - Add the `array!`, `azip!`, and `s!` macros to `ndarray::prelude` - ([#517](https://github.com/rust-ndarray/ndarray/pull/517) by [@jturner314]) +- `ndarray-parallel` is merged into `ndarray`. Use the `rayon` feature-flag to get access to parallel iterators and + other parallelized methods. + ([#563](https://github.com/rust-ndarray/ndarray/pull/563/files) by [@bluss]) +- Add `logspace` and `geomspace` constructors + ([#617](https://github.com/rust-ndarray/ndarray/pull/617) by [@JP-Ellis]) +- Implement approx traits for `ArrayBase`. They can be enabled using the `approx` feature-flag. + ([#581](https://github.com/rust-ndarray/ndarray/pull/581) by [@jturner314]) +- Add `mean` method + ([#580](https://github.com/rust-ndarray/ndarray/pull/580) by [@LukeMathWalker]) +- Add `Zip::all` to check if all elements satisfy a predicate + ([#615](https://github.com/rust-ndarray/ndarray/pull/615) by [@mneumann]) +- Add `RawArrayView` and `RawArrayViewMut` types and `RawData`, `RawDataMut`, and `RawDataClone` traits + ([#496](https://github.com/rust-ndarray/ndarray/pull/496) by [@jturner314]) +- Add `CowArray`, `C`lone `o`n `write` array + ([#632](https://github.com/rust-ndarray/ndarray/pull/632) by [@jturner314] and [@andrei-papou]) +- Add `as_standard_layout` to `ArrayBase`: it takes an array by reference and returns a `CoWArray` in standard layout + ([#616](https://github.com/rust-ndarray/ndarray/pull/616) by [@jturner314] and [@andrei-papou]) +- Add `Array2::from_diag` method to create 2D arrays from a diagonal + ([#673](https://github.com/rust-ndarray/ndarray/pull/673) by [@rth]) +- Add `fold` method to `Zip` + ([#684](https://github.com/rust-ndarray/ndarray/pull/684) by [@jturner314]) +- Add `split_at` method to `AxisChunksIter/Mut` + ([#691](https://github.com/rust-ndarray/ndarray/pull/691) by [@jturner314]) +- Implement parallel iteration for `AxisChunksIter/Mut` + ([#639](https://github.com/rust-ndarray/ndarray/pull/639) by [@nitsky]) +- Add `into_scalar` method to `ArrayView0` and `ArrayViewMut0` + ([#700](https://github.com/rust-ndarray/ndarray/pull/700) by [@LukeMathWalker]) +- Add `accumulate_axis_inplace` method to `ArrayBase` + ([#611](https://github.com/rust-ndarray/ndarray/pull/611) by [@jturner314] and [@bluss]) +- Add the `array!`, `azip!`, and `s!` macros to `ndarray::prelude` + ([#517](https://github.com/rust-ndarray/ndarray/pull/517) by [@jturner314]) Enhancements ------------ - - Improve performance for matrix multiplications when using the pure-Rust backend thanks to `matrix-multiply:v0.2` - (leverage SIMD instructions on x86-64 with runtime feature detection) - ([#556](https://github.com/rust-ndarray/ndarray/pull/556) by [@bluss]) - - Improve performance of `fold` for iterators - ([#574](https://github.com/rust-ndarray/ndarray/pull/574) by [@jturner314]) - - Improve performance of `nth_back` for iterators - ([#686](https://github.com/rust-ndarray/ndarray/pull/686) by [@jturner314]) - - Improve performance of iterators for 1-d arrays - ([#614](https://github.com/rust-ndarray/ndarray/pull/614) by [@andrei-papou]) - - Improve formatting for large arrays - ([#606](https://github.com/rust-ndarray/ndarray/pull/606) by [@andrei-papou] and [@LukeMathWalker], - [#633](https://github.com/rust-ndarray/ndarray/pull/633) and [#707](https://github.com/rust-ndarray/ndarray/pull/707) by [@jturner314], - and [#713](https://github.com/rust-ndarray/ndarray/pull/713) by [@bluss]) - - Arithmetic operations between arrays with different element types are now allowed when there is a scalar equivalent - ([#588](https://github.com/rust-ndarray/ndarray/pull/588) by [@jturner314]) - - `.map_axis/_mut` won't panic on 0-length `axis` - ([#579](https://github.com/rust-ndarray/ndarray/pull/612) by [@andrei-papou]) - - Various documentation improvements (by [@jturner314], [@JP-Ellis], [@LukeMathWalker], [@bluss]) + +- Improve performance for matrix multiplications when using the pure-Rust backend thanks to `matrix-multiply:v0.2` + (leverage SIMD instructions on x86-64 with runtime feature detection) + ([#556](https://github.com/rust-ndarray/ndarray/pull/556) by [@bluss]) +- Improve performance of `fold` for iterators + ([#574](https://github.com/rust-ndarray/ndarray/pull/574) by [@jturner314]) +- Improve performance of `nth_back` for iterators + ([#686](https://github.com/rust-ndarray/ndarray/pull/686) by [@jturner314]) +- Improve performance of iterators for 1-d arrays + ([#614](https://github.com/rust-ndarray/ndarray/pull/614) by [@andrei-papou]) +- Improve formatting for large arrays + ([#606](https://github.com/rust-ndarray/ndarray/pull/606) by [@andrei-papou] and [@LukeMathWalker], + [#633](https://github.com/rust-ndarray/ndarray/pull/633) and [#707](https://github.com/rust-ndarray/ndarray/pull/707) + by [@jturner314], + and [#713](https://github.com/rust-ndarray/ndarray/pull/713) by [@bluss]) +- Arithmetic operations between arrays with different element types are now allowed when there is a scalar equivalent + ([#588](https://github.com/rust-ndarray/ndarray/pull/588) by [@jturner314]) +- `.map_axis/_mut` won't panic on 0-length `axis` + ([#579](https://github.com/rust-ndarray/ndarray/pull/612) by [@andrei-papou]) +- Various documentation improvements (by [@jturner314], [@JP-Ellis], [@LukeMathWalker], [@bluss]) API changes ----------- - - The `into_slice` method on ArrayView is deprecated and renamed to `to_slice` - ([#646](https://github.com/rust-ndarray/ndarray/pull/646) by [@max-sixty]) - - `RcArray` is deprecated in favour of `ArcArray` - ([#560](https://github.com/rust-ndarray/ndarray/pull/560) by [@bluss]) - - `into_slice` is renamed to `to_slice`. `into_slice` is now deprecated - ([#646](https://github.com/rust-ndarray/ndarray/pull/646) by [@max-sixty]) - - `from_vec` is deprecated in favour of using the `From` to convert a `Vec` into an `Array` - ([#648](https://github.com/rust-ndarray/ndarray/pull/648) by [@max-sixty]) - - `mean_axis` returns `Option` instead of `A`, to avoid panicking when invoked on a 0-length axis - ([#580](https://github.com/rust-ndarray/ndarray/pull/580) by [@LukeMathWalker]) - - Remove `rustc-serialize` feature-flag. `serde` is the recommended feature-flag for serialization - ([#557](https://github.com/rust-ndarray/ndarray/pull/557) by [@bluss]) - - `rows`/`cols` are renamed to `nrows`/`ncols`. `rows`/`cols` are now deprecated - ([#701](https://github.com/rust-ndarray/ndarray/pull/701) by [@bluss]) - - The usage of the `azip!` macro has changed to be more similar to `for` loops - ([#626](https://github.com/rust-ndarray/ndarray/pull/626) by [@jturner314]) - - For `var_axis` and `std_axis`, the constraints on `ddof` and the trait bounds on `A` have been made more strict - ([#515](https://github.com/rust-ndarray/ndarray/pull/515) by [@jturner314]) - - For `mean_axis`, the constraints on `A` have changed - ([#518](https://github.com/rust-ndarray/ndarray/pull/518) by [@jturner314]) - - `DataClone` is deprecated in favor of using `Data + RawDataClone` - ([#496](https://github.com/rust-ndarray/ndarray/pull/496) by [@jturner314]) - - The `Dimension::Pattern` associated type now has more trait bounds - ([#634](https://github.com/rust-ndarray/ndarray/pull/634) by [@termoshtt]) - - `Axis::index()` now takes `self` instead of `&self` - ([#642](https://github.com/rust-ndarray/ndarray/pull/642) by [@max-sixty]) - - The bounds on the implementation of `Hash` for `Dim` have changed - ([#642](https://github.com/rust-ndarray/ndarray/pull/642) by [@max-sixty]) + +- The `into_slice` method on ArrayView is deprecated and renamed to `to_slice` + ([#646](https://github.com/rust-ndarray/ndarray/pull/646) by [@max-sixty]) +- `RcArray` is deprecated in favour of `ArcArray` + ([#560](https://github.com/rust-ndarray/ndarray/pull/560) by [@bluss]) +- `into_slice` is renamed to `to_slice`. `into_slice` is now deprecated + ([#646](https://github.com/rust-ndarray/ndarray/pull/646) by [@max-sixty]) +- `from_vec` is deprecated in favour of using the `From` to convert a `Vec` into an `Array` + ([#648](https://github.com/rust-ndarray/ndarray/pull/648) by [@max-sixty]) +- `mean_axis` returns `Option` instead of `A`, to avoid panicking when invoked on a 0-length axis + ([#580](https://github.com/rust-ndarray/ndarray/pull/580) by [@LukeMathWalker]) +- Remove `rustc-serialize` feature-flag. `serde` is the recommended feature-flag for serialization + ([#557](https://github.com/rust-ndarray/ndarray/pull/557) by [@bluss]) +- `rows`/`cols` are renamed to `nrows`/`ncols`. `rows`/`cols` are now deprecated + ([#701](https://github.com/rust-ndarray/ndarray/pull/701) by [@bluss]) +- The usage of the `azip!` macro has changed to be more similar to `for` loops + ([#626](https://github.com/rust-ndarray/ndarray/pull/626) by [@jturner314]) +- For `var_axis` and `std_axis`, the constraints on `ddof` and the trait bounds on `A` have been made more strict + ([#515](https://github.com/rust-ndarray/ndarray/pull/515) by [@jturner314]) +- For `mean_axis`, the constraints on `A` have changed + ([#518](https://github.com/rust-ndarray/ndarray/pull/518) by [@jturner314]) +- `DataClone` is deprecated in favor of using `Data + RawDataClone` + ([#496](https://github.com/rust-ndarray/ndarray/pull/496) by [@jturner314]) +- The `Dimension::Pattern` associated type now has more trait bounds + ([#634](https://github.com/rust-ndarray/ndarray/pull/634) by [@termoshtt]) +- `Axis::index()` now takes `self` instead of `&self` + ([#642](https://github.com/rust-ndarray/ndarray/pull/642) by [@max-sixty]) +- The bounds on the implementation of `Hash` for `Dim` have changed + ([#642](https://github.com/rust-ndarray/ndarray/pull/642) by [@max-sixty]) Bug fixes --------- - - Prevent overflow when computing strides in `do_slice` - ([#575](https://github.com/rust-ndarray/ndarray/pull/575) by [@jturner314]) - - Fix issue with BLAS matrix-vector multiplication for array with only 1 non-trivial dimension - ([#585](https://github.com/rust-ndarray/ndarray/pull/585) by [@sebasv]) - - Fix offset computation to avoid UB/panic when slicing in some edge cases - ([#636](https://github.com/rust-ndarray/ndarray/pull/636) by [@jturner314]) - - Fix issues with axis iterators - ([#669](https://github.com/rust-ndarray/ndarray/pull/669) by [@jturner314]) - - Fix handling of empty input to `s!` macro - ([#714](https://github.com/rust-ndarray/ndarray/pull/714) by [@bluss] and [#715](https://github.com/rust-ndarray/ndarray/pull/715) by [@jturner314]) + +- Prevent overflow when computing strides in `do_slice` + ([#575](https://github.com/rust-ndarray/ndarray/pull/575) by [@jturner314]) +- Fix issue with BLAS matrix-vector multiplication for array with only 1 non-trivial dimension + ([#585](https://github.com/rust-ndarray/ndarray/pull/585) by [@sebasv]) +- Fix offset computation to avoid UB/panic when slicing in some edge cases + ([#636](https://github.com/rust-ndarray/ndarray/pull/636) by [@jturner314]) +- Fix issues with axis iterators + ([#669](https://github.com/rust-ndarray/ndarray/pull/669) by [@jturner314]) +- Fix handling of empty input to `s!` macro + ([#714](https://github.com/rust-ndarray/ndarray/pull/714) by [@bluss] + and [#715](https://github.com/rust-ndarray/ndarray/pull/715) by [@jturner314]) Other changes ------------- - - Various improvements to `ndarray`'s CI pipeline (`clippy`, `cargo fmt`, etc. by [@max-sixty] and [@termoshtt]) - - Bump minimum required Rust version to 1.37. +- Various improvements to `ndarray`'s CI pipeline (`clippy`, `cargo fmt`, etc. by [@max-sixty] and [@termoshtt]) +- Bump minimum required Rust version to 1.37. Version 0.12.1 (2018-11-21) =========================== - - Add `std_axis` method for computing standard deviation by @LukeMathWalker. - - Add `product` method for computing product of elements in an array by @sebasv. - - Add `first` and `first_mut` methods for getting the first element of an array. - - Add `into_scalar` method for converting an `Array0` into its element. - - Add `insert_axis_inplace` and `index_axis_inplace` methods for inserting and - removing axes in dynamic-dimensional (`IxDyn`) arrays without taking ownership. - - Add `stride_of` method for getting the stride of an axis. - - Add public `ndim` and `zeros` methods to `Dimension` trait. - - Rename `scalar_sum` to `sum`, `subview` to `index_axis`, - `subview_mut` to `index_axis_mut`, `subview_inplace` to - `collapse_axis`, `into_subview` to `index_axis_move`, and - `slice_inplace` to `slice_collapse` (deprecating the old names, - except for `scalar_sum` which will be in 0.13). - - Deprecate `remove_axis` and fix soundness hole when removing a zero-length axis. - - Implement `Clone` for `LanesIter`. - - Implement `Debug`, `Copy`, and `Clone` for `FoldWhile`. - - Relax constraints on `sum_axis`, `mean_axis`, and `into_owned`. - - Add number of dimensions (and whether it's const or dynamic) to array `Debug` format. - - Allow merging axes with `merge_axes` when either axis length is ≤ 1. - - Clarify and check more precise safety requirements for constructing arrays. - This fixes undefined behavior in some edge cases. - (See [#543](https://github.com/rust-ndarray/ndarray/pull/543).) - - Fix `is_standard_layout` in some edge cases. - (See [#543](https://github.com/rust-ndarray/ndarray/pull/543).) - - Fix chunk sizes in `axis_chunks_iter` and `axis_chunks_iter_mut` when - the stride is zero or the array element type is zero-sized by @bluss. - - Improve documentation by @jturner314, @bluss, and @paulkernfeld. - - Improve element iterators with implementations of `Iterator::rfold`. - - Miscellaneous internal implementation improvements by @jturner314 and @bluss. - +- Add `std_axis` method for computing standard deviation by @LukeMathWalker. +- Add `product` method for computing product of elements in an array by @sebasv. +- Add `first` and `first_mut` methods for getting the first element of an array. +- Add `into_scalar` method for converting an `Array0` into its element. +- Add `insert_axis_inplace` and `index_axis_inplace` methods for inserting and + removing axes in dynamic-dimensional (`IxDyn`) arrays without taking ownership. +- Add `stride_of` method for getting the stride of an axis. +- Add public `ndim` and `zeros` methods to `Dimension` trait. +- Rename `scalar_sum` to `sum`, `subview` to `index_axis`, + `subview_mut` to `index_axis_mut`, `subview_inplace` to + `collapse_axis`, `into_subview` to `index_axis_move`, and + `slice_inplace` to `slice_collapse` (deprecating the old names, + except for `scalar_sum` which will be in 0.13). +- Deprecate `remove_axis` and fix soundness hole when removing a zero-length axis. +- Implement `Clone` for `LanesIter`. +- Implement `Debug`, `Copy`, and `Clone` for `FoldWhile`. +- Relax constraints on `sum_axis`, `mean_axis`, and `into_owned`. +- Add number of dimensions (and whether it's const or dynamic) to array `Debug` format. +- Allow merging axes with `merge_axes` when either axis length is ≤ 1. +- Clarify and check more precise safety requirements for constructing arrays. + This fixes undefined behavior in some edge cases. + (See [#543](https://github.com/rust-ndarray/ndarray/pull/543).) +- Fix `is_standard_layout` in some edge cases. + (See [#543](https://github.com/rust-ndarray/ndarray/pull/543).) +- Fix chunk sizes in `axis_chunks_iter` and `axis_chunks_iter_mut` when + the stride is zero or the array element type is zero-sized by @bluss. +- Improve documentation by @jturner314, @bluss, and @paulkernfeld. +- Improve element iterators with implementations of `Iterator::rfold`. +- Miscellaneous internal implementation improvements by @jturner314 and @bluss. Version 0.12.0 (2018-09-01) =========================== - - Add `var_axis` method for computing variance by @LukeMathWalker. - - Add `map_mut` and `map_axis_mut` methods (mutable variants of `map` and `map_axis`) by @LukeMathWalker. - - Add support for 128-bit integer scalars (`i128` and `u128`). - - Add support for slicing with inclusive ranges (`start..=end` and `..=end`). - - Relax constraint on closure from `Fn` to `FnMut` for `mapv`, `mapv_into`, `map_inplace` and `mapv_inplace`. - - Implement `TrustedIterator` for `IterMut`. - - Bump `num-traits` and `num-complex` to version `0.2`. - - Bump `blas-src` to version `0.2`. - - Bump minimum required Rust version to 1.27. - - Additional contributors to this release: @ExpHP, @jturner314, @alexbool, @messense, @danmack, @nbro +- Add `var_axis` method for computing variance by @LukeMathWalker. +- Add `map_mut` and `map_axis_mut` methods (mutable variants of `map` and `map_axis`) by @LukeMathWalker. +- Add support for 128-bit integer scalars (`i128` and `u128`). +- Add support for slicing with inclusive ranges (`start..=end` and `..=end`). +- Relax constraint on closure from `Fn` to `FnMut` for `mapv`, `mapv_into`, `map_inplace` and `mapv_inplace`. +- Implement `TrustedIterator` for `IterMut`. +- Bump `num-traits` and `num-complex` to version `0.2`. +- Bump `blas-src` to version `0.2`. +- Bump minimum required Rust version to 1.27. +- Additional contributors to this release: @ExpHP, @jturner314, @alexbool, @messense, @danmack, @nbro Version 0.11.2 (2018-03-21) =========================== - - New documentation; @jturner314 has written a large “ndarray for NumPy users” - document, which we include in rustdoc. - [Read it here](https://docs.rs/ndarray/0.11/ndarray/doc/ndarray_for_numpy_users/) - a useful quick guide for any user, and in particular if you are familiar - with numpy. - - Add `ArcArray`. `RcArray` has become `ArcArray`; it is now using thread - safe reference counting just like `Arc`; this means that shared ownership - arrays are now `Send/Sync` if the corresponding element type is `Send +- New documentation; @jturner314 has written a large “ndarray for NumPy users” + document, which we include in rustdoc. + [Read it here](https://docs.rs/ndarray/0.11/ndarray/doc/ndarray_for_numpy_users/) + a useful quick guide for any user, and in particular if you are familiar + with numpy. +- Add `ArcArray`. `RcArray` has become `ArcArray`; it is now using thread + safe reference counting just like `Arc`; this means that shared ownership + arrays are now `Send/Sync` if the corresponding element type is `Send + Sync`. - - Add array method `.permute_axes()` by @jturner314 - - Add array constructor `Array::ones` by @ehsanmok - - Add the method `.reborrow()` to `ArrayView/Mut`, which can be used - to shorten the lifetime of an array view; in a reference-like type this - normally happens implicitly but for technical reasons the views have - an invariant lifetime parameter. - - Fix an issue with type inference, the dimensionality of an array - should not infer correctly in more cases when using slicing. By @jturner314. - +- Add array method `.permute_axes()` by @jturner314 +- Add array constructor `Array::ones` by @ehsanmok +- Add the method `.reborrow()` to `ArrayView/Mut`, which can be used + to shorten the lifetime of an array view; in a reference-like type this + normally happens implicitly but for technical reasons the views have + an invariant lifetime parameter. +- Fix an issue with type inference, the dimensionality of an array + should not infer correctly in more cases when using slicing. By @jturner314. Version 0.11.1 (2018-01-21) =========================== - - Dimension types (`Ix1, Ix2, .., IxDyn`) now implement `Hash` by - @jturner314 - - Blas integration can now use *gemv* for matrix-vector multiplication also - when the matrix is f-order by @maciejkula - - Encapsulated `unsafe` code blocks in the `s![]` macro are now exempted - from the `unsafe_code` lint by @jturner314 +- Dimension types (`Ix1, Ix2, .., IxDyn`) now implement `Hash` by + @jturner314 +- Blas integration can now use *gemv* for matrix-vector multiplication also + when the matrix is f-order by @maciejkula +- Encapsulated `unsafe` code blocks in the `s![]` macro are now exempted + from the `unsafe_code` lint by @jturner314 Version 0.11.0 (2017-12-29) =========================== [Release announcement](https://jim.turner.link/pages/ndarray-0.11/) - - Allow combined slicing and subviews in a single operation by @jturner314 and - @bluss +- Allow combined slicing and subviews in a single operation by @jturner314 and + @bluss * Add support for individual indices (to indicate subviews) to the `s![]` macro, and change the return type to @@ -909,725 +903,763 @@ Version 0.11.0 (2017-12-29) * Replace the `Si` type with `SliceOrIndex`. * Add a new `Slice` type that is similar to the old `Si` type. - - Add support for more index types (e.g. `usize`) to the `s![]` macro by - @jturner314 - - Rename `.islice()` to `.slice_inplace()` by @jturner314 - - Rename `.isubview()` to `.subview_inplace()` by @jturner314 - - Add `.slice_move()`, `.slice_axis()`, `.slice_axis_mut()`, and - `.slice_axis_inplace()` methods by @jturner314 - - Add `Dimension::NDIM` associated constant by @jturner314 - - Change trait bounds for arithmetic ops between an array (by value) and - a reference to an array or array view (“array1 (op) &array2”); before, - an `ArrayViewMut` was supported on the left hand side, now, the left - hand side must not be a view. - ([#380](https://github.com/rust-ndarray/ndarray/pull/380)) by @jturner314 - - Remove deprecated methods (`.whole_chunks()`, `.whole_chunks_mut()`, - `.sum()`, and `.mean()`; replaced by `.exact_chunks()`, - `.exact_chunks_mut()`, `.sum_axis()`, and `.mean_axis()`, - respectively) by @bluss - - Updated to the latest blas (optional) dependencies. See instructions in the - README. - - Minimum required Rust version is 1.22. - +- Add support for more index types (e.g. `usize`) to the `s![]` macro by + @jturner314 +- Rename `.islice()` to `.slice_inplace()` by @jturner314 +- Rename `.isubview()` to `.subview_inplace()` by @jturner314 +- Add `.slice_move()`, `.slice_axis()`, `.slice_axis_mut()`, and + `.slice_axis_inplace()` methods by @jturner314 +- Add `Dimension::NDIM` associated constant by @jturner314 +- Change trait bounds for arithmetic ops between an array (by value) and + a reference to an array or array view (“array1 (op) &array2”); before, + an `ArrayViewMut` was supported on the left hand side, now, the left + hand side must not be a view. + ([#380](https://github.com/rust-ndarray/ndarray/pull/380)) by @jturner314 +- Remove deprecated methods (`.whole_chunks()`, `.whole_chunks_mut()`, + `.sum()`, and `.mean()`; replaced by `.exact_chunks()`, + `.exact_chunks_mut()`, `.sum_axis()`, and `.mean_axis()`, + respectively) by @bluss +- Updated to the latest blas (optional) dependencies. See instructions in the + README. +- Minimum required Rust version is 1.22. Earlier releases ================ - 0.10.13 - - Add an extension trait for longer-life indexing methods for array views - (`IndexLonger`) by @termoshtt and @bluss - - The `a.dot(b)` method now supports a vector times matrix multiplication - by @jturner314 - - More general `.into_owned()` method by @jturner314 + - Add an extension trait for longer-life indexing methods for array views + (`IndexLonger`) by @termoshtt and @bluss + - The `a.dot(b)` method now supports a vector times matrix multiplication + by @jturner314 + - More general `.into_owned()` method by @jturner314 - 0.10.12 - - Implement serde serialization for `IxDyn`, so that arrays and array views - using it are serializable as well. + - Implement serde serialization for `IxDyn`, so that arrays and array views + using it are serializable as well. - 0.10.11 - - Add method `.uswap(a, b)` for unchecked swap by @jturner314 - - Bump private dependencies (itertools 0.7) + - Add method `.uswap(a, b)` for unchecked swap by @jturner314 + - Bump private dependencies (itertools 0.7) - 0.10.10 - - Fix crash with zero size arrays in the fallback matrix multiplication code - (#365) by @jturner314 + - Fix crash with zero size arrays in the fallback matrix multiplication code + (#365) by @jturner314 - 0.10.9 - - Fix crash in `Array::from_shape_fn` when creating an f-order array - with zero elements (#361) by @jturner314 + - Fix crash in `Array::from_shape_fn` when creating an f-order array + with zero elements (#361) by @jturner314 - 0.10.8 - - Add method `.insert_axis()` to arrays and array views by @jturner314 + - Add method `.insert_axis()` to arrays and array views by @jturner314 - 0.10.7 - - Add method `.is_empty()` to arrays and array views by @iamed2 - - Support optional trailing commas in the `array![]` macro by Alex Burka - - Added an example of permuting/sorting along an axis to the sources + - Add method `.is_empty()` to arrays and array views by @iamed2 + - Support optional trailing commas in the `array![]` macro by Alex Burka + - Added an example of permuting/sorting along an axis to the sources - 0.10.6 - - Tweak the implementation for (bounds checked) indexing of arrays - ([] operator). The new code will have the optimizer elide the bounds checks - in more situations. + - Tweak the implementation for (bounds checked) indexing of arrays + ([] operator). The new code will have the optimizer elide the bounds checks + in more situations. - 0.10.5 - - Add method `.into_dimensionality::()` for dimensionality conversion - (From `IxDyn` to fixed size and back). - - New names `.sum_axis` and `.mean_axis` for sum and mean functions. - Old names deprecated to make room for scalar-returning methods, making - a proper convention. - - Fix deserialization using ron (#345) by @Libbum + - Add method `.into_dimensionality::()` for dimensionality conversion + (From `IxDyn` to fixed size and back). + - New names `.sum_axis` and `.mean_axis` for sum and mean functions. + Old names deprecated to make room for scalar-returning methods, making + a proper convention. + - Fix deserialization using ron (#345) by @Libbum - 0.10.4 - - Fix unused mut warnings in `azip!()` macro - - Fix bug #340 by @lloydmeta; uses blas gemm for more memory layouts - of column matrices. Only relevant if using blas. + - Fix unused mut warnings in `azip!()` macro + - Fix bug #340 by @lloydmeta; uses blas gemm for more memory layouts + of column matrices. Only relevant if using blas. - 0.10.3 - - Fix docs.rs doc build + - Fix docs.rs doc build - 0.10.2 - - Support trailing commas in the `s![]` macro - - Some documentation improvements for the introduction, for `azip!()` and - other places. - - Added two more examples in the source + - Support trailing commas in the `s![]` macro + - Some documentation improvements for the introduction, for `azip!()` and + other places. + - Added two more examples in the source - 0.10.1 - - Add method `.into_dyn()` to convert to a dynamic dimensionality array - or array view. By @bobogei81123 - - Edit docs for the fact that type alias pages now show methods. - See the doc pages for `Array` and `ArrayView` and the other aliases. - - Edit docs for `Zip` + - Add method `.into_dyn()` to convert to a dynamic dimensionality array + or array view. By @bobogei81123 + - Edit docs for the fact that type alias pages now show methods. + See the doc pages for `Array` and `ArrayView` and the other aliases. + - Edit docs for `Zip` - 0.10.0 - - Upgrade to Serde 1.0. Crate feature name is `serde-1`. - - Require Rust 1.18. The `pub(crate)` feature is that important. + - Upgrade to Serde 1.0. Crate feature name is `serde-1`. + - Require Rust 1.18. The `pub(crate)` feature is that important. - 0.9.1 - - Fix `Array::from_shape_fn` to give correct indices for f-order shapes - - Fix `Array::from_shape_fn` to panic correctly on shape size overflow + - Fix `Array::from_shape_fn` to give correct indices for f-order shapes + - Fix `Array::from_shape_fn` to panic correctly on shape size overflow - 0.9.0 [Release Announcement](https://bluss.github.io//rust/2017/04/09/ndarray-0.9/) - - Add `Zip::indexed` - - New methods `genrows/_mut, gencolumns/_mut, lanes/_mut` that - return iterable producers (producer means `Zip` compatible). - - New method `.windows()` by @Robbepop, returns an iterable producer - - New function `general_mat_vec_mul` (with fast default and blas acceleration) - - `Zip::apply` and `fold_while` now take `self` as the first argument - - `indices/_of` now return iterable producers (not iterator) - - No allocation for short `IxDyn`. - - Remove `Ix, Ixs` from the prelude - - Remove deprecated `Axis::axis` method (use `.index()`) - - Rename `.whole_chunks` to `.exact_chunks`. - - Remove `.inner_iter` in favour of the new `.genrows()` method. - - Iterators and similar structs are now scoped under `ndarray::iter` - - `IntoNdProducer` now has the `Item` associated type - - Owned array storage types are now encapsulated in newtypes - - `FoldWhile` got the method `is_done`. - - Arrays now implement formatting trait `Binary` if elements do - - Internal changes. `NdProducer` generalized. `Dimension` gets - the `Smaller` type parameter. Internal traits have the private marker now. - - `#` (alternate) in formatting does nothing now. - - Require Rust 1.15 + - Add `Zip::indexed` + - New methods `genrows/_mut, gencolumns/_mut, lanes/_mut` that + return iterable producers (producer means `Zip` compatible). + - New method `.windows()` by @Robbepop, returns an iterable producer + - New function `general_mat_vec_mul` (with fast default and blas acceleration) + - `Zip::apply` and `fold_while` now take `self` as the first argument + - `indices/_of` now return iterable producers (not iterator) + - No allocation for short `IxDyn`. + - Remove `Ix, Ixs` from the prelude + - Remove deprecated `Axis::axis` method (use `.index()`) + - Rename `.whole_chunks` to `.exact_chunks`. + - Remove `.inner_iter` in favour of the new `.genrows()` method. + - Iterators and similar structs are now scoped under `ndarray::iter` + - `IntoNdProducer` now has the `Item` associated type + - Owned array storage types are now encapsulated in newtypes + - `FoldWhile` got the method `is_done`. + - Arrays now implement formatting trait `Binary` if elements do + - Internal changes. `NdProducer` generalized. `Dimension` gets + the `Smaller` type parameter. Internal traits have the private marker now. + - `#` (alternate) in formatting does nothing now. + - Require Rust 1.15 - 0.8.4 - - Use `Zip` in `.all_close()` (performance improvement) - - Use `#[inline]` on a function used for higher dimensional checked - indexing (performance improvement for arrays of ndim >= 3) - - `.subview()` has a more elaborate panic message + - Use `Zip` in `.all_close()` (performance improvement) + - Use `#[inline]` on a function used for higher dimensional checked + indexing (performance improvement for arrays of ndim >= 3) + - `.subview()` has a more elaborate panic message - 0.8.3 - - Fix a bug in `Zip` / `NdProducer` if an array of at least 3 dimensions - was contig but not c- nor f-contig. - - `WholeChunksIter/Mut` now impl `Send/Sync` as appropriate - - Misc cleanup and using dimension-reducing versions of inner_iter - internally. Remove a special case in `zip_mut_with` that only made it - slower (1D not-contig arrays). + - Fix a bug in `Zip` / `NdProducer` if an array of at least 3 dimensions + was contig but not c- nor f-contig. + - `WholeChunksIter/Mut` now impl `Send/Sync` as appropriate + - Misc cleanup and using dimension-reducing versions of inner_iter + internally. Remove a special case in `zip_mut_with` that only made it + slower (1D not-contig arrays). - 0.8.2 - - Add more documentation and an example for dynamic dimensions: see - [`IxDyn`](https://docs.rs/ndarray/0.8.2/ndarray/type.IxDyn.html). - `IxDyn` will have a representation change next incompatible - version. Use it as a type alias for best forward compatibility. - - Add iterable and producer `.whole_chunks_mut(size)`. - - Fix a bug in `whole_chunks`: it didn't check the dimensionality of the - requested chunk size properly (an `IxDyn`-only bug). - - Improve performance of `zip_mut_with` (and thus all binary operators) for - block slices of row major arrays. - - `AxisChunksIter` creation sped up and it implements `Clone`. - - Dimension mismatch in `Zip` has a better panic message. + - Add more documentation and an example for dynamic dimensions: see + [`IxDyn`](https://docs.rs/ndarray/0.8.2/ndarray/type.IxDyn.html). + `IxDyn` will have a representation change next incompatible + version. Use it as a type alias for best forward compatibility. + - Add iterable and producer `.whole_chunks_mut(size)`. + - Fix a bug in `whole_chunks`: it didn't check the dimensionality of the + requested chunk size properly (an `IxDyn`-only bug). + - Improve performance of `zip_mut_with` (and thus all binary operators) for + block slices of row major arrays. + - `AxisChunksIter` creation sped up and it implements `Clone`. + - Dimension mismatch in `Zip` has a better panic message. - 0.8.1 - - Add `Zip` and macro `azip!()` which implement lock step function - application across elements from one up to six arrays (or in general - producers) + - Add `Zip` and macro `azip!()` which implement lock step function + application across elements from one up to six arrays (or in general + producers) - + Apart from array views, axis iterators and the whole chunks iterable are - also producers + + Apart from array views, axis iterators and the whole chunks iterable are + also producers - - Add constructor `Array::uninitialized` - - Add iterable and producer `.whole_chunks(size)` - - Implement a prettier `Debug` for `Si`. - - Fix `Array::default` so that it panics as documented if the size of the - array would wrap around integer type limits. - - Output more verbose panics for errors when slicing arrays (only in debug - mode). + - Add constructor `Array::uninitialized` + - Add iterable and producer `.whole_chunks(size)` + - Implement a prettier `Debug` for `Si`. + - Fix `Array::default` so that it panics as documented if the size of the + array would wrap around integer type limits. + - Output more verbose panics for errors when slicing arrays (only in debug + mode). - 0.8.0 - - Update serde dependency to 0.9 - - Remove deprecated type alias `OwnedArray` (use `Array`) - - Remove deprecated `.assign_scalar()` (use `fill`) + - Update serde dependency to 0.9 + - Remove deprecated type alias `OwnedArray` (use `Array`) + - Remove deprecated `.assign_scalar()` (use `fill`) - 0.7.3 - - Add macro `array![]` for creating one-, two-, or three-dimensional arrays - (with ownership semantics like `vec![]`) - - `Array` now implements `Clone::clone_from()` specifically, so that its - allocation is (possibly) reused. - - Add `.to_vec()` for one-dimensional arrays - - Add `RcArray::into_owned(self) -> Array`. - - Add crate categories + - Add macro `array![]` for creating one-, two-, or three-dimensional arrays + (with ownership semantics like `vec![]`) + - `Array` now implements `Clone::clone_from()` specifically, so that its + allocation is (possibly) reused. + - Add `.to_vec()` for one-dimensional arrays + - Add `RcArray::into_owned(self) -> Array`. + - Add crate categories - 0.7.2 - - Add array methods `.remove_axis()`, `.merge_axes()` and `.invert_axis()` - - Rename `Axis`’ accessor `axis` to `index`, old name is deprecated. + - Add array methods `.remove_axis()`, `.merge_axes()` and `.invert_axis()` + - Rename `Axis`’ accessor `axis` to `index`, old name is deprecated. - 0.7.1 - - Fix two bugs in `Array::clone()`; it did not support zero-size elements - like `()`, and for some negatively strided arrays it did not update the - first element offset correctly. - - Add `.axes()` which is an iterator over the axes of an array, yielding - its index, length and stride. - - Add method `.max_stride_axis()`. + - Fix two bugs in `Array::clone()`; it did not support zero-size elements + like `()`, and for some negatively strided arrays it did not update the + first element offset correctly. + - Add `.axes()` which is an iterator over the axes of an array, yielding + its index, length and stride. + - Add method `.max_stride_axis()`. - 0.6.10 - - Fix two bugs in `Array::clone()`; it did not support zero-size elements - like `()`, and for some negatively strided arrays it did not update the - first element offset correctly. + - Fix two bugs in `Array::clone()`; it did not support zero-size elements + like `()`, and for some negatively strided arrays it did not update the + first element offset correctly. - 0.7.0 - - Big overhaul of dimensions: Add type `Dim` with aliases - `Ix1, Ix2, Ix3, ...` etc for specific dimensionalities. - Instead of `Ix` for dimension use `Ix1`, instead of `(Ix, Ix)` use - `Ix2`, and so on. - - The dimension type `Dim` supports indexing and arithmetic. See - `Dimension` trait for new methods and inherited traits. - - Constructors and methods that take tuples for array sizes, like `Array::zeros,` - `Array::from_shape_vec`, `.into_shape()` and so on will continue to work - with tuples. - - The array method `.raw_dim()` returns the shape description - `D` as it is. `.dim()` continues to return the dimension as a tuple. - - Renamed iterators for consistency (each iterator is named for the - method that creates it, for example `.iter()` returns `Iter`). - - The index iterator is now created with free functions `indices` or - `indices_of`. - - Expanded the `ndarray::prelude` module with the dimensionality-specific - type aliases, and some other items - - `LinalgScalar` and related features no longer need to use `Any` for - static type dispatch. - - Serialization with `serde` now supports binary encoders like bincode - and others. - - `.assign_scalar()` was deprecated and replaced by `.fill()`, which - takes an element by value. - - Require Rust 1.13 + - Big overhaul of dimensions: Add type `Dim` with aliases + `Ix1, Ix2, Ix3, ...` etc for specific dimensionalities. + Instead of `Ix` for dimension use `Ix1`, instead of `(Ix, Ix)` use + `Ix2`, and so on. + - The dimension type `Dim` supports indexing and arithmetic. See + `Dimension` trait for new methods and inherited traits. + - Constructors and methods that take tuples for array sizes, like `Array::zeros,` + `Array::from_shape_vec`, `.into_shape()` and so on will continue to work + with tuples. + - The array method `.raw_dim()` returns the shape description + `D` as it is. `.dim()` continues to return the dimension as a tuple. + - Renamed iterators for consistency (each iterator is named for the + method that creates it, for example `.iter()` returns `Iter`). + - The index iterator is now created with free functions `indices` or + `indices_of`. + - Expanded the `ndarray::prelude` module with the dimensionality-specific + type aliases, and some other items + - `LinalgScalar` and related features no longer need to use `Any` for + static type dispatch. + - Serialization with `serde` now supports binary encoders like bincode + and others. + - `.assign_scalar()` was deprecated and replaced by `.fill()`, which + takes an element by value. + - Require Rust 1.13 - 0.6.9 - - Implement `ExactSizeIterator` for the indexed iterators + - Implement `ExactSizeIterator` for the indexed iterators - 0.6.8 - - Fix a bug in a partially consumed elements iterator's `.fold()`. - (**Note** that users are recommended to not use the elements iterator, - but the higher level functions which are the maps, folds and other methods - of the array types themselves.) + - Fix a bug in a partially consumed elements iterator's `.fold()`. + (**Note** that users are recommended to not use the elements iterator, + but the higher level functions which are the maps, folds and other methods + of the array types themselves.) - 0.6.7 - - Improve performance of a lot of basic operations for arrays where - the innermost dimension is not contiguous (`.fold(), .map(), - .to_owned()`, arithmetic operations with scalars). - - Require Rust 1.11 + - Improve performance of a lot of basic operations for arrays where + the innermost dimension is not contiguous (`.fold(), .map(), + .to_owned()`, arithmetic operations with scalars). + - Require Rust 1.11 - 0.6.6 - - Add dimensionality specific type aliases: `Array0, Array1, Array2, ...` - and so on (there are many), also `Ix0, Ix1, Ix2, ...`. - - Add constructor `Array::from_shape_fn(D, |D| -> A)`. - - Improve performance of `Array::default`, and `.fold()` for noncontiguous - array iterators. + - Add dimensionality specific type aliases: `Array0, Array1, Array2, ...` + and so on (there are many), also `Ix0, Ix1, Ix2, ...`. + - Add constructor `Array::from_shape_fn(D, |D| -> A)`. + - Improve performance of `Array::default`, and `.fold()` for noncontiguous + array iterators. - 0.6.5 - - Add method `.into_raw_vec()` to turn an `Array` into the its - underlying element storage vector, in whatever element order it is using. + - Add method `.into_raw_vec()` to turn an `Array` into the its + underlying element storage vector, in whatever element order it is using. - 0.6.4 - - Add method `.map_axis()` which is used to flatten an array along - one axis by mapping it to a scalar. + - Add method `.map_axis()` which is used to flatten an array along + one axis by mapping it to a scalar. - 0.6.3 - - Work around compilation issues in nightly (issue #217) - - Add `Default` implementations for owned arrays + - Work around compilation issues in nightly (issue #217) + - Add `Default` implementations for owned arrays - 0.6.2 - - Add serialization support for serde 0.8, under the crate feature name `serde` + - Add serialization support for serde 0.8, under the crate feature name `serde` - 0.6.1 - - Add `unsafe` array view constructors `ArrayView::from_shape_ptr` - for read-only and read-write array views. These make it easier to - create views from raw pointers. + - Add `unsafe` array view constructors `ArrayView::from_shape_ptr` + for read-only and read-write array views. These make it easier to + create views from raw pointers. - 0.6.0 - - Rename `OwnedArray` to `Array`. The old name is deprecated. - - Remove deprecated constructor methods. Use zeros, from_elem, from_shape_vec - or from_shape_vec_unchecked instead. - - Remove deprecated in place arithmetic methods like iadd et.c. Use += et.c. - instead. - - Remove deprecated method mat_mul, use dot instead. - - Require Rust 1.9 + - Rename `OwnedArray` to `Array`. The old name is deprecated. + - Remove deprecated constructor methods. Use zeros, from_elem, from_shape_vec + or from_shape_vec_unchecked instead. + - Remove deprecated in place arithmetic methods like iadd et.c. Use += et.c. + instead. + - Remove deprecated method mat_mul, use dot instead. + - Require Rust 1.9 - 0.5.2 - - Use num-traits, num-complex instead of num. + - Use num-traits, num-complex instead of num. - 0.5.1 - - Fix theoretical well-formedness issue with Data trait + - Fix theoretical well-formedness issue with Data trait - 0.5.0 - - Require Rust 1.8 and enable +=, -=, and the other assign operators. - All `iadd, iadd_scalar` and similar methods are now deprecated. - - ndarray now has a prelude: `use ndarray::prelude::*;`. - - Constructors from_elem, zeros, from_shape_vec now all support passing a custom - memory layout. A lot of specific constructors were deprecated. - - Add method `.select(Axis, &[Ix]) -> OwnedArray`, to create an array - from a non-contiguous pick of subviews along an axis. - - Rename `.mat_mul()` to just `.dot()` and add a function `general_mat_mul` - for matrix multiplication with scaling into an existing array. - - **Change .fold() to use arbitrary order.** - - See below for more details + - Require Rust 1.8 and enable +=, -=, and the other assign operators. + All `iadd, iadd_scalar` and similar methods are now deprecated. + - ndarray now has a prelude: `use ndarray::prelude::*;`. + - Constructors from_elem, zeros, from_shape_vec now all support passing a custom + memory layout. A lot of specific constructors were deprecated. + - Add method `.select(Axis, &[Ix]) -> OwnedArray`, to create an array + from a non-contiguous pick of subviews along an axis. + - Rename `.mat_mul()` to just `.dot()` and add a function `general_mat_mul` + for matrix multiplication with scaling into an existing array. + - **Change .fold() to use arbitrary order.** + - See below for more details - 0.5.0-alpha.2 - - Fix a namespace bug in the stack![] macro. - - Add method .select() that can pick an arbitrary set of rows (for example) - into a new array. + - Fix a namespace bug in the stack![] macro. + - Add method .select() that can pick an arbitrary set of rows (for example) + into a new array. - 0.4.9 - - Fix a namespace bug in the stack![] macro. - - Add deprecation messages to .iadd() and similar methods (use += instead). + - Fix a namespace bug in the stack![] macro. + - Add deprecation messages to .iadd() and similar methods (use += instead). - 0.5.0-alpha.1 - - Add .swap(i, j) for swapping two elements - - Add a prelude module `use ndarray::prelude::*;` - - Add ndarray::linalg::general_mat_mul which computes *C ← α A B + β C*, - i.e matrix multiplication into an existing array, with optional scaling. - - Add .fold_axis(Axis, folder) - - Implement .into_shape() for f-order arrays + - Add .swap(i, j) for swapping two elements + - Add a prelude module `use ndarray::prelude::*;` + - Add ndarray::linalg::general_mat_mul which computes *C ← α A B + β C*, + i.e matrix multiplication into an existing array, with optional scaling. + - Add .fold_axis(Axis, folder) + - Implement .into_shape() for f-order arrays - 0.5.0-alpha.0 - - Requires Rust 1.8. Compound assignment operators are now enabled by default. - - Rename `.mat_mul()` to `.dot()`. The same method name now handles - dot product and matrix multiplication. - - Remove deprecated items: raw_data, raw_data_mut, allclose, zeros, Array. - Docs for 0.4. lists the replacements. - - Remove deprecated crate features: rblas, assign_ops - - A few consuming arithmetic ops with ArrayViewMut were removed (this - was missed in the last version). - - **Change .fold() to use arbitrary order.** Its specification and - implementation has changed, to pick the most appropriate element traversal - order depending on memory layout. + - Requires Rust 1.8. Compound assignment operators are now enabled by default. + - Rename `.mat_mul()` to `.dot()`. The same method name now handles + dot product and matrix multiplication. + - Remove deprecated items: raw_data, raw_data_mut, allclose, zeros, Array. + Docs for 0.4. lists the replacements. + - Remove deprecated crate features: rblas, assign_ops + - A few consuming arithmetic ops with ArrayViewMut were removed (this + was missed in the last version). + - **Change .fold() to use arbitrary order.** Its specification and + implementation has changed, to pick the most appropriate element traversal + order depending on memory layout. - 0.4.8 - - Fix an error in `.dot()` when using BLAS and arrays with negative stride. + - Fix an error in `.dot()` when using BLAS and arrays with negative stride. - 0.4.7 - - Add dependency matrixmultiply to handle matrix multiplication - for floating point elements. It supports matrices of general stride - and is a great improvement for performance. See PR #175. + - Add dependency matrixmultiply to handle matrix multiplication + for floating point elements. It supports matrices of general stride + and is a great improvement for performance. See PR #175. - 0.4.6 - - Fix bug with crate feature blas; it would not compute matrix - multiplication correctly for arrays with negative or zero stride. - - Update blas-sys version (optional dependency). + - Fix bug with crate feature blas; it would not compute matrix + multiplication correctly for arrays with negative or zero stride. + - Update blas-sys version (optional dependency). - 0.4.5 - - Add `.all_close()` which replaces the now deprecated `.allclose()`. - The new method has a stricter protocol: it panics if the array - shapes are not compatible. We don't want errors to pass silently. - - Add a new illustration to the doc for `.axis_iter()`. - - Rename `OuterIter, OuterIterMut` to `AxisIter, AxisIterMut`. - The old name is now deprecated. + - Add `.all_close()` which replaces the now deprecated `.allclose()`. + The new method has a stricter protocol: it panics if the array + shapes are not compatible. We don't want errors to pass silently. + - Add a new illustration to the doc for `.axis_iter()`. + - Rename `OuterIter, OuterIterMut` to `AxisIter, AxisIterMut`. + The old name is now deprecated. - 0.4.4 - - Add mapping methods `.mapv(), .mapv_into(), .map_inplace(),` - `.mapv_inplace(), .visit()`. The `mapv` versions - have the transformation function receive the element by value (hence *v*). - - Add method `.scaled_add()` (a.k.a axpy) and constructor `from_vec_dim_f`. - - Add 2d array methods `.rows(), .cols()`. - - Deprecate method `.fold()` because it dictates a specific visit order. + - Add mapping methods `.mapv(), .mapv_into(), .map_inplace(),` + `.mapv_inplace(), .visit()`. The `mapv` versions + have the transformation function receive the element by value (hence *v*). + - Add method `.scaled_add()` (a.k.a axpy) and constructor `from_vec_dim_f`. + - Add 2d array methods `.rows(), .cols()`. + - Deprecate method `.fold()` because it dictates a specific visit order. - 0.4.3 - - Add array method `.t()` as a shorthand to create a transposed view. - - Fix `mat_mul` so that it accepts arguments of different array kind - - Fix a bug in `mat_mul` when using BLAS and multiplying with a column - matrix (#154) + - Add array method `.t()` as a shorthand to create a transposed view. + - Fix `mat_mul` so that it accepts arguments of different array kind + - Fix a bug in `mat_mul` when using BLAS and multiplying with a column + matrix (#154) - 0.4.2 - - Add new BLAS integration used by matrix multiplication - (selected with crate feature `blas`). Uses pluggable backend. - - Deprecate module `ndarray::blas` and crate feature `rblas`. This module - was moved to the crate `ndarray-rblas`. - - Add array methods `as_slice_memory_order, as_slice_memory_order_mut, as_ptr, - as_mut_ptr`. - - Deprecate `raw_data, raw_data_mut`. - - Add `Send + Sync` to `NdFloat`. - - Arrays now show shape & stride in their debug formatter. - - Fix a bug where `from_vec_dim_stride` did not accept arrays with unitary axes. - - Performance improvements for contiguous arrays in non-c order when using - methods `to_owned, map, scalar_sum, assign_scalar`, - and arithmetic operations between array and scalar. - - Some methods now return arrays in the same memory order of the input - if the input is contiguous: `to_owned, map, mat_mul` (matrix multiplication - only if both inputs are the same memory order), and arithmetic operations - that allocate a new result. - - Slight performance improvements in `dot, mat_mul` due to more efficient - glue code for calling BLAS. - - Performance improvements in `.assign_scalar`. + - Add new BLAS integration used by matrix multiplication + (selected with crate feature `blas`). Uses pluggable backend. + - Deprecate module `ndarray::blas` and crate feature `rblas`. This module + was moved to the crate `ndarray-rblas`. + - Add array methods `as_slice_memory_order, as_slice_memory_order_mut, as_ptr, + as_mut_ptr`. + - Deprecate `raw_data, raw_data_mut`. + - Add `Send + Sync` to `NdFloat`. + - Arrays now show shape & stride in their debug formatter. + - Fix a bug where `from_vec_dim_stride` did not accept arrays with unitary axes. + - Performance improvements for contiguous arrays in non-c order when using + methods `to_owned, map, scalar_sum, assign_scalar`, + and arithmetic operations between array and scalar. + - Some methods now return arrays in the same memory order of the input + if the input is contiguous: `to_owned, map, mat_mul` (matrix multiplication + only if both inputs are the same memory order), and arithmetic operations + that allocate a new result. + - Slight performance improvements in `dot, mat_mul` due to more efficient + glue code for calling BLAS. + - Performance improvements in `.assign_scalar`. - 0.4.1 - - Mark iterators `Send + Sync` when possible. + - Mark iterators `Send + Sync` when possible. - **0.4.0** [Release Announcement](http://bluss.github.io/rust/2016/03/06/ndarray-0.4/) - - New array splitting via `.split_at(Axis, Ix)` and `.axis_chunks_iter()` - - Added traits `NdFloat`, `AsArray` and `From for ArrayView` which - improve generic programming. - - Array constructors panic when attempting to create an array whose element - count overflows `usize`. (Would be a debug assertion for overflow before.) - - Performance improvements for `.map()`. - - Added `stack` and macro `stack![axis, arrays..]` to concatenate arrays. - - Added constructor `OwnedArray::range(start, end, step)`. - - The type alias `Array` was renamed to `RcArray` (and the old name deprecated). - - Binary operators are not defined when consuming a mutable array view as - the left hand side argument anymore. - - Remove methods and items deprecated since 0.3 or earlier; deprecated methods - have notes about replacements in 0.3 docs. - - See below for full changelog through alphas. + - New array splitting via `.split_at(Axis, Ix)` and `.axis_chunks_iter()` + - Added traits `NdFloat`, `AsArray` and `From for ArrayView` which + improve generic programming. + - Array constructors panic when attempting to create an array whose element + count overflows `usize`. (Would be a debug assertion for overflow before.) + - Performance improvements for `.map()`. + - Added `stack` and macro `stack![axis, arrays..]` to concatenate arrays. + - Added constructor `OwnedArray::range(start, end, step)`. + - The type alias `Array` was renamed to `RcArray` (and the old name deprecated). + - Binary operators are not defined when consuming a mutable array view as + the left hand side argument anymore. + - Remove methods and items deprecated since 0.3 or earlier; deprecated methods + have notes about replacements in 0.3 docs. + - See below for full changelog through alphas. - 0.4.0-alpha.8 - - In debug mode, indexing an array out of bounds now has a detailed - message about index and shape. (In release mode it does not.) - - Enable assign_ops feature automatically when it is supported (Rust 1.8 beta - or later). - - Add trait `NdFloat` which makes it easy to be generic over `f32, f64`. - - Add `From` implementations that convert slices or references to arrays - into array views. This replaces `from_slice` from a previous alpha. - - Add `AsArray` trait, which is simply based on those `From` implementations. - - Improve `.map()` so that it can autovectorize. - - Use `Axis` argument in `RemoveAxis` too. - - Require `DataOwned` in the raw data methods. - - Merged error types into a single `ShapeError`, which uses no allocated data. + - In debug mode, indexing an array out of bounds now has a detailed + message about index and shape. (In release mode it does not.) + - Enable assign_ops feature automatically when it is supported (Rust 1.8 beta + or later). + - Add trait `NdFloat` which makes it easy to be generic over `f32, f64`. + - Add `From` implementations that convert slices or references to arrays + into array views. This replaces `from_slice` from a previous alpha. + - Add `AsArray` trait, which is simply based on those `From` implementations. + - Improve `.map()` so that it can autovectorize. + - Use `Axis` argument in `RemoveAxis` too. + - Require `DataOwned` in the raw data methods. + - Merged error types into a single `ShapeError`, which uses no allocated data. - 0.4.0-alpha.7 - - Fix too strict lifetime bound in arithmetic operations like `&a @ &b`. - - Rename trait Scalar to ScalarOperand (and improve its docs). - - Implement <<= and >>= for arrays. + - Fix too strict lifetime bound in arithmetic operations like `&a @ &b`. + - Rename trait Scalar to ScalarOperand (and improve its docs). + - Implement <<= and >>= for arrays. - 0.4.0-alpha.6 - - All axis arguments must now be wrapped in newtype `Axis`. - - Add method `.split_at(Axis, Ix)` to read-only and read-write array views. - - Add constructors `ArrayView{,Mut}::from_slice` and array view methods - are now visible in the docs. + - All axis arguments must now be wrapped in newtype `Axis`. + - Add method `.split_at(Axis, Ix)` to read-only and read-write array views. + - Add constructors `ArrayView{,Mut}::from_slice` and array view methods + are now visible in the docs. - 0.4.0-alpha.5 - - Use new trait `LinalgScalar` for operations where we want type-based specialization. - This shrinks the set of types that allow dot product, matrix multiply, mean. - - Use BLAS acceleration transparently in `.dot()` (this is the first step). - - Only OwnedArray and RcArray and not ArrayViewMut can now be used as consumed - left hand operand for arithmetic operators. [See arithmetic operations docs!]( - https://docs.rs/ndarray/0.4.0-alpha.5/ndarray/struct.ArrayBase.html#arithmetic-operations) - - Remove deprecated module `linalg` (it was already mostly empty) - - Deprecate free function `zeros` in favour of static method `zeros`. + - Use new trait `LinalgScalar` for operations where we want type-based specialization. + This shrinks the set of types that allow dot product, matrix multiply, mean. + - Use BLAS acceleration transparently in `.dot()` (this is the first step). + - Only OwnedArray and RcArray and not ArrayViewMut can now be used as consumed + left hand operand for arithmetic operators. [See arithmetic operations docs!]( + https://docs.rs/ndarray/0.4.0-alpha.5/ndarray/struct.ArrayBase.html#arithmetic-operations) + - Remove deprecated module `linalg` (it was already mostly empty) + - Deprecate free function `zeros` in favour of static method `zeros`. - 0.4.0-alpha.4 - - Rename `Array` to `RcArray`. Old name is deprecated. - - Add methods `OuterIter::split_at`, `OuterIterMut::split_at` - - Change `arr0, arr1, arr2, arr3` to return `OwnedArray`. - Add `rcarr1, rcarr2, rcarr3` that return `RcArray`. + - Rename `Array` to `RcArray`. Old name is deprecated. + - Add methods `OuterIter::split_at`, `OuterIterMut::split_at` + - Change `arr0, arr1, arr2, arr3` to return `OwnedArray`. + Add `rcarr1, rcarr2, rcarr3` that return `RcArray`. - 0.4.0-alpha.3 - - Improve arithmetic operations where the RHS is a broadcast 0-dimensional - array. - - Add read-only and read-write array views to the `rblas` integration. - Added methods `AsBlas::{blas_view_checked, blas_view_mut_checked, bv, bvm}`. - - Use hash_slice in `Hash` impl for arrays. + - Improve arithmetic operations where the RHS is a broadcast 0-dimensional + array. + - Add read-only and read-write array views to the `rblas` integration. + Added methods `AsBlas::{blas_view_checked, blas_view_mut_checked, bv, bvm}`. + - Use hash_slice in `Hash` impl for arrays. - 0.4.0-alpha.2 - - Add `ArrayBase::reversed_axes` which transposes an array. + - Add `ArrayBase::reversed_axes` which transposes an array. - 0.4.0-alpha.1 - - Add checked and unchecked constructor methods for creating arrays - from a vector and explicit dimension and stride, or with - fortran (column major) memory order (marked `f`): - - + `ArrayBase::from_vec_dim`, `from_vec_dim_stride`, - `from_vec_dim_stride_unchecked`, - + `from_vec_dim_unchecked_f`, `from_elem_f`, `zeros_f` - + View constructors `ArrayView::from_slice_dim_stride`, - `ArrayViewMut::from_slice_dim_stride`. - + Rename old `ArrayBase::from_vec_dim` to `from_vec_dim_unchecked`. - - - Check better for wraparound when computing the number of elements in a shape; - this adds error cases that **panic** in `from_elem`, `zeros` etc, - however *the new check will only ever panic in cases that would - trigger debug assertions for overflow in the previous versions*!. - - Add an array chunks iterator `.axis_chunks_iter()` and mutable version; - it allows traversing the array in for example chunks of *n* rows at a time. - - Remove methods and items deprecated since 0.3 or earlier; deprecated methods - have notes about replacements in 0.3 docs. + - Add checked and unchecked constructor methods for creating arrays + from a vector and explicit dimension and stride, or with + fortran (column major) memory order (marked `f`): + + + `ArrayBase::from_vec_dim`, `from_vec_dim_stride`, + `from_vec_dim_stride_unchecked`, + + `from_vec_dim_unchecked_f`, `from_elem_f`, `zeros_f` + + View constructors `ArrayView::from_slice_dim_stride`, + `ArrayViewMut::from_slice_dim_stride`. + + Rename old `ArrayBase::from_vec_dim` to `from_vec_dim_unchecked`. + + - Check better for wraparound when computing the number of elements in a shape; + this adds error cases that **panic** in `from_elem`, `zeros` etc, + however *the new check will only ever panic in cases that would + trigger debug assertions for overflow in the previous versions*!. + - Add an array chunks iterator `.axis_chunks_iter()` and mutable version; + it allows traversing the array in for example chunks of *n* rows at a time. + - Remove methods and items deprecated since 0.3 or earlier; deprecated methods + have notes about replacements in 0.3 docs. - 0.3.1 - - Add `.row_mut()`, `.column_mut()` - - Add `.axis_iter()`, `.axis_iter_mut()` + - Add `.row_mut()`, `.column_mut()` + - Add `.axis_iter()`, `.axis_iter_mut()` - **0.3.0** - - Second round of API & consistency update is done - - 0.3.0 highlight: **Index type** `Ix` **changed to** `usize`. - - 0.3.0 highlight: Operator overloading for scalar and array arithmetic. - - 0.3.0 highlight: Indexing with `a[[i, j, k]]` syntax. - - Add `ArrayBase::eye(n)` - - See below for more info + - Second round of API & consistency update is done + - 0.3.0 highlight: **Index type** `Ix` **changed to** `usize`. + - 0.3.0 highlight: Operator overloading for scalar and array arithmetic. + - 0.3.0 highlight: Indexing with `a[[i, j, k]]` syntax. + - Add `ArrayBase::eye(n)` + - See below for more info - 0.3.0-alpha.4 - - Shrink array view structs by removing their redundant slice field (see #45). - Changed the definition of the view `type` aliases. - - `.mat_mul()` and `.mat_mul_col()` now return `OwnedArray`. - Use `.into_shared()` if you need an `Array`. - - impl ExactSizeIterator where possible for iterators. - - impl DoubleEndedIterator for `.outer_iter()` (and _mut). + - Shrink array view structs by removing their redundant slice field (see #45). + Changed the definition of the view `type` aliases. + - `.mat_mul()` and `.mat_mul_col()` now return `OwnedArray`. + Use `.into_shared()` if you need an `Array`. + - impl ExactSizeIterator where possible for iterators. + - impl DoubleEndedIterator for `.outer_iter()` (and _mut). - 0.3.0-alpha.3 - - `.subview()` changed to return an array view, also added `into_subview()`. - - Add `.outer_iter()` and `.outer_iter_mut()` for iteration along the - greatest axis of the array. Views also implement `into_outer_iter()` for - “lifetime preserving” iterators. + - `.subview()` changed to return an array view, also added `into_subview()`. + - Add `.outer_iter()` and `.outer_iter_mut()` for iteration along the + greatest axis of the array. Views also implement `into_outer_iter()` for + “lifetime preserving” iterators. - 0.3.0-alpha.2 - - Improve the strided last dimension case in `zip_mut_with` slightly - (affects all binary operations). - - Add `.row(i), .column(i)` for 2D arrays. - - Deprecate `.row_iter(), .col_iter()`. - - Add method `.dot()` for computing the dot product between two 1D arrays. + - Improve the strided last dimension case in `zip_mut_with` slightly + (affects all binary operations). + - Add `.row(i), .column(i)` for 2D arrays. + - Deprecate `.row_iter(), .col_iter()`. + - Add method `.dot()` for computing the dot product between two 1D arrays. - 0.3.0-alpha.1 - - **Index type** `Ix` **changed to** `usize` (#9). Gives better iterator codegen - and 64-bit size arrays. - - Support scalar operands with arithmetic operators. - - Change `.slice()` and `.diag()` to return array views, add `.into_diag()`. - - Add ability to use fixed size arrays for array indexing, enabling syntax - like `a[[i, j]]` for indexing. - - Add `.ndim()` + - **Index type** `Ix` **changed to** `usize` (#9). Gives better iterator codegen + and 64-bit size arrays. + - Support scalar operands with arithmetic operators. + - Change `.slice()` and `.diag()` to return array views, add `.into_diag()`. + - Add ability to use fixed size arrays for array indexing, enabling syntax + like `a[[i, j]]` for indexing. + - Add `.ndim()` - **0.2.0** - - First chapter of API and performance evolution is done \\o/ - - 0.2.0 highlight: Vectorized (efficient) arithmetic operations - - 0.2.0 highlight: Easier slicing using `s![]` - - 0.2.0 highlight: Nicer API using views - - 0.2.0 highlight: Bridging to BLAS functions. - - See below for more info + - First chapter of API and performance evolution is done \\o/ + - 0.2.0 highlight: Vectorized (efficient) arithmetic operations + - 0.2.0 highlight: Easier slicing using `s![]` + - 0.2.0 highlight: Nicer API using views + - 0.2.0 highlight: Bridging to BLAS functions. + - See below for more info - 0.2.0-alpha.9 - - Support strided matrices in `rblas` bridge, and fix a bug with - non square matrices. - - Deprecated all of module `linalg`. + - Support strided matrices in `rblas` bridge, and fix a bug with + non square matrices. + - Deprecated all of module `linalg`. - 0.2.0-alpha.8 - - **Note:** PACKAGE NAME CHANGED TO `ndarray`. Having package != crate ran - into many quirks of various tools. Changing the package name is easier for - everyone involved! - - Optimized `scalar_sum()` so that it will vectorize for the floating point - element case too. + - **Note:** PACKAGE NAME CHANGED TO `ndarray`. Having package != crate ran + into many quirks of various tools. Changing the package name is easier for + everyone involved! + - Optimized `scalar_sum()` so that it will vectorize for the floating point + element case too. - 0.2.0-alpha.7 - - Optimized arithmetic operations! + - Optimized arithmetic operations! - - For c-contiguous arrays or arrays with c-contiguous lowest dimension - they optimize very well, and can vectorize! + - For c-contiguous arrays or arrays with c-contiguous lowest dimension + they optimize very well, and can vectorize! - - Add `.inner_iter()`, `.inner_iter_mut()` - - Add `.fold()`, `.zip_mut_with()` - - Add `.scalar_sum()` - - Add example `examples/life.rs` + - Add `.inner_iter()`, `.inner_iter_mut()` + - Add `.fold()`, `.zip_mut_with()` + - Add `.scalar_sum()` + - Add example `examples/life.rs` - 0.2.0-alpha.6 - - Add `#[deprecated]` attributes (enabled with new enough nightly) - - Add `ArrayBase::linspace`, deprecate constructor `range`. + - Add `#[deprecated]` attributes (enabled with new enough nightly) + - Add `ArrayBase::linspace`, deprecate constructor `range`. - 0.2.0-alpha.5 - - Add `s![...]`, a slice argument macro. - - Add `aview_mut1()`, `zeros()` - - Add `.diag_mut()` and deprecate `.diag_iter_mut()`, `.sub_iter_mut()` - - Add `.uget()`, `.uget_mut()` for unchecked indexing and deprecate the - old names. - - Improve `ArrayBase::from_elem` - - Removed `SliceRange`, replaced by `From` impls for `Si`. + - Add `s![...]`, a slice argument macro. + - Add `aview_mut1()`, `zeros()` + - Add `.diag_mut()` and deprecate `.diag_iter_mut()`, `.sub_iter_mut()` + - Add `.uget()`, `.uget_mut()` for unchecked indexing and deprecate the + old names. + - Improve `ArrayBase::from_elem` + - Removed `SliceRange`, replaced by `From` impls for `Si`. - 0.2.0-alpha.4 - - Slicing methods like `.slice()` now take a fixed size array of `Si` - as the slice description. This allows more type checking to verify that the - number of axes is correct. - - Add experimental `rblas` integration. - - Add `into_shape()` which allows reshaping any array or view kind. + - Slicing methods like `.slice()` now take a fixed size array of `Si` + as the slice description. This allows more type checking to verify that the + number of axes is correct. + - Add experimental `rblas` integration. + - Add `into_shape()` which allows reshaping any array or view kind. - 0.2.0-alpha.3 - - Add and edit a lot of documentation + - Add and edit a lot of documentation - 0.2.0-alpha.2 - - Improve performance for iterators when the array data is in the default - memory layout. The iterator then wraps the default slice iterator and - loops will autovectorize. - - Remove method `.indexed()` on iterators. Changed `Indexed` and added - `ÌndexedMut`. - - Added `.as_slice(), .as_mut_slice()` - - Support rustc-serialize + - Improve performance for iterators when the array data is in the default + memory layout. The iterator then wraps the default slice iterator and + loops will autovectorize. + - Remove method `.indexed()` on iterators. Changed `Indexed` and added + `ÌndexedMut`. + - Added `.as_slice(), .as_mut_slice()` + - Support rustc-serialize - 0.2.0-alpha - - Alpha release! - - Introduce `ArrayBase`, `OwnedArray`, `ArrayView`, `ArrayViewMut` - - All arithmetic operations should accept any array type - - `Array` continues to refer to the default reference counted copy on write - array - - Add `.view()`, `.view_mut()`, `.to_owned()`, `.into_shared()` - - Add `.slice_mut()`, `.subview_mut()` - - Some operations now return `OwnedArray`: + - Alpha release! + - Introduce `ArrayBase`, `OwnedArray`, `ArrayView`, `ArrayViewMut` + - All arithmetic operations should accept any array type + - `Array` continues to refer to the default reference counted copy on write + array + - Add `.view()`, `.view_mut()`, `.to_owned()`, `.into_shared()` + - Add `.slice_mut()`, `.subview_mut()` + - Some operations now return `OwnedArray`: - - `.map()` - - `.sum()` - - `.mean()` + - `.map()` + - `.sum()` + - `.mean()` - - Add `get`, `get_mut` to replace the now deprecated `at`, `at_mut`. - - Fix bug in assign_scalar + - Add `get`, `get_mut` to replace the now deprecated `at`, `at_mut`. + - Fix bug in assign_scalar - 0.1.1 - - Add Array::default - - Fix bug in raw_data_mut + - Add Array::default + - Fix bug in raw_data_mut - 0.1.0 - - First release on crates.io - - Starting point for evolution to come - + - First release on crates.io + - Starting point for evolution to come [@adamreichold]: https://github.com/adamreichold + [@aganders3]: https://github.com/aganders3 + [@bluss]: https://github.com/bluss + [@jturner314]: https://github.com/jturner314 + [@LukeMathWalker]: https://github.com/LukeMathWalker + [@acj]: https://github.com/acj + [@adamreichold]: https://github.com/adamreichold + [@atouchet]: https://github.com/atouchet + [@andrei-papou]: https://github.com/andrei-papou + [@benkay]: https://github.com/benkay + [@cassiersg]: https://github.com/cassiersg + [@chohner]: https://github.com/chohner + [@dam5h]: https://github.com/dam5h + [@ethanhs]: https://github.com/ethanhs + [@d-dorazio]: https://github.com/d-dorazio + [@Eijebong]: https://github.com/Eijebong + [@HyeokSuLee]: https://github.com/HyeokSuLee + [@insideoutclub]: https://github.com/insideoutclub + [@JP-Ellis]: https://github.com/JP-Ellis + [@jimblandy]: https://github.com/jimblandy + [@LeSeulArtichaut]: https://github.com/LeSeulArtichaut + [@lifuyang]: https://github.com/liufuyang + [@kdubovikov]: https://github.com/kdubovikov + [@makotokato]: https://github.com/makotokato + [@max-sixty]: https://github.com/max-sixty + [@mneumann]: https://github.com/mneumann + [@mockersf]: https://github.com/mockersf + [@nilgoyette]: https://github.com/nilgoyette + [@nitsky]: https://github.com/nitsky + [@Rikorose]: https://github.com/Rikorose + [@rth]: https://github.com/rth + [@sebasv]: https://github.com/sebasv + [@SparrowLii]: https://github.com/SparrowLii + [@steffahn]: https://github.com/steffahn + [@stokhos]: https://github.com/stokhos + [@termoshtt]: https://github.com/termoshtt + [@TheLortex]: https://github.com/TheLortex + [@viniciusd]: https://github.com/viniciusd + [@VasanthakumarV]: https://github.com/VasanthakumarV + [@xd009642]: https://github.com/xd009642 + [@Zuse64]: https://github.com/Zuse64 diff --git a/misc/axis_iter.svg b/misc/axis_iter.svg index ea4157b0e..9394d110d 100644 --- a/misc/axis_iter.svg +++ b/misc/axis_iter.svg @@ -2,840 +2,841 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="274.07394mm" + height="131.17035mm" + viewBox="0 0 971.12814 464.77682" + id="svg6730" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="axis_iter.svg"> + + + + + + + + + + + + + + + + image/svg+xml + + + + + - - - - - - - - - - - - - - - - - - - - - - - + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + style="opacity:1" + transform="translate(-7.6612808,-76.544459)"> + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Axis(0) - Axis(1) - Axis(2) - .axis_iter(Axis(2)) - Input shape: (3, 4, 5)Output shapes: (3, 4) - - - - - - - Input shape: (3, 4, 5) + Output shapes: (3, 4) + + + + + + + 0 - 1 - 2 - 3 - 4 + + - - diff --git a/misc/split_at.svg b/misc/split_at.svg index 57c429546..67e7439b2 100644 --- a/misc/split_at.svg +++ b/misc/split_at.svg @@ -2,796 +2,797 @@ - - - - - - - - - - - - - - - - image/svg+xml - - - - - - + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + width="189.43846mm" + height="171.03487mm" + viewBox="0 0 671.23864 606.02905" + id="svg6730" + version="1.1" + inkscape:version="0.91 r13725" + sodipodi:docname="split_at.svg"> + + + + + + + + + + + + + + + + image/svg+xml + + + + + - - - - - - - - - - - - - - - - - - - - - - - + inkscape:label="Layer 1" + inkscape:groupmode="layer" + id="layer1" + style="opacity:1" + transform="translate(-7.6612808,-76.544459)"> + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Axis(0) - Axis(1) - Axis(2) - .split_at(Axis(2), 2) - Input shape: (3, 5, 5)Output shapes: (3, 5, 2) and (3, 5, 3) - - + id="tspan8614-6">Input shape: (3, 5, 5) + Output shapes: (3, 5, 2) and (3, 5, 3) + + diff --git a/ndarray-rand/README.md b/ndarray-rand/README.md index 0109e9732..e7f42d95a 100644 --- a/ndarray-rand/README.md +++ b/ndarray-rand/README.md @@ -28,8 +28,8 @@ Dependencies ``ndarray-rand`` depends on ``rand``. -[`rand`](https://docs.rs/rand/) and [`rand-distr`](https://docs.rs/rand_distr/) are -re-exported as sub-modules, `ndarray_rand::rand` and `ndarray_rand::rand_distr` respectively. +[`rand`](https://docs.rs/rand/) and [`rand-distr`](https://docs.rs/rand_distr/) are +re-exported as sub-modules, `ndarray_rand::rand` and `ndarray_rand::rand_distr` respectively. Please rely on these submodules for guaranteed version compatibility. If you want to use a random number generator or distribution from another crate @@ -41,7 +41,7 @@ necessary trait). Recent changes ============== -Check _[RELEASES.md](https://github.com/rust-ndarray/ndarray/blob/master/ndarray-rand/RELEASES.md)_ to see +Check _[RELEASES.md](https://github.com/rust-ndarray/ndarray/blob/master/ndarray-rand/RELEASES.md)_ to see the changes introduced in previous releases. diff --git a/ndarray-rand/RELEASES.md b/ndarray-rand/RELEASES.md index 8d7586fbe..1557e1ddc 100644 --- a/ndarray-rand/RELEASES.md +++ b/ndarray-rand/RELEASES.md @@ -3,73 +3,73 @@ Recent Changes - 0.14.0 - - Require ndarray 0.15 - - Require rand 0.8 (unchanged from previous version) - - The F32 wrapper is now deprecated, it's redundant + - Require ndarray 0.15 + - Require rand 0.8 (unchanged from previous version) + - The F32 wrapper is now deprecated, it's redundant - 0.13.0 - - Require ndarray 0.14 (unchanged from previous version) - - Require rand 0.8 - - Require rand_distr 0.4 - - Fix methods `sample_axis` and `sample_axis_using` so that they can be used on array views too. + - Require ndarray 0.14 (unchanged from previous version) + - Require rand 0.8 + - Require rand_distr 0.4 + - Fix methods `sample_axis` and `sample_axis_using` so that they can be used on array views too. - 0.12.0 - - Require ndarray 0.14 - - Require rand 0.7 (unchanged from previous version) - - Require rand_distr 0.3 + - Require ndarray 0.14 + - Require rand 0.7 (unchanged from previous version) + - Require rand_distr 0.3 - 0.11.0 - - Require ndarray 0.13 - - Require rand 0.7 (unchanged from previous version) + - Require ndarray 0.13 + - Require rand 0.7 (unchanged from previous version) - 0.10.0 - - Require `rand` 0.7 - - Require Rust 1.32 or later - - Re-export `rand` as a submodule, `ndarray_rand::rand` - - Re-export `rand-distr` as a submodule, `ndarray_rand::rand_distr` + - Require `rand` 0.7 + - Require Rust 1.32 or later + - Re-export `rand` as a submodule, `ndarray_rand::rand` + - Re-export `rand-distr` as a submodule, `ndarray_rand::rand_distr` - 0.9.0 - - Require rand 0.6 + - Require rand 0.6 - 0.8.0 - - Require ndarray 0.12 - - Require rand 0.5 + - Require ndarray 0.12 + - Require rand 0.5 - 0.7.0 - - Require ndarray 0.11 - - Require rand 0.4 + - Require ndarray 0.11 + - Require rand 0.4 - 0.6.1 - - Clean up implementation of ``Array::random`` by @v-shmyhlo + - Clean up implementation of ``Array::random`` by @v-shmyhlo - 0.6.0 - - Require ndarray 0.10.0 + - Require ndarray 0.10.0 - 0.5.0 - - Require ndarray 0.9 + - Require ndarray 0.9 - 0.4.0 - - Require ndarray 0.8 + - Require ndarray 0.8 - 0.3.0 - - Require ndarray 0.7 + - Require ndarray 0.7 - 0.2.0 - - Require ndarray 0.6 + - Require ndarray 0.6 - 0.1.0 - - Initial release + - Initial release diff --git a/scripts/all-tests.sh b/scripts/all-tests.sh index cbea6dba7..569f84c36 100755 --- a/scripts/all-tests.sh +++ b/scripts/all-tests.sh @@ -6,7 +6,7 @@ set -e FEATURES=$1 CHANNEL=$2 -if [ "$CHANNEL" = "1.57.0" ]; then +if [ "$CHANNEL" = "1.63.0" ]; then cargo update --package openblas-src --precise 0.10.5 cargo update --package openblas-build --precise 0.10.5 cargo update --package once_cell --precise 1.14.0 @@ -21,21 +21,46 @@ if [ "$CHANNEL" = "1.57.0" ]; then cargo update --package serde_json --precise 1.0.99 cargo update --package serde --precise 1.0.156 cargo update --package thiserror --precise 1.0.39 - cargo update --package quote --precise 1.0.30 - cargo update --package proc-macro2 --precise 1.0.65 + cargo update --package quote --precise 1.0.35 + cargo update --package proc-macro2 --precise 1.0.79 + cargo update --package regex --precise 1.9.6 + cargo update --package home --precise 0.5.5 + cargo update --package which --precise 4.4.2 + cargo update --package rustix --precise 0.38.23 + cargo update --package memchr --precise 2.6.2 fi cargo build --verbose --no-default-features + # Testing both dev and release profiles helps find bugs, especially in low level code cargo test --verbose --no-default-features cargo test --release --verbose --no-default-features + cargo build --verbose --features "$FEATURES" cargo test --verbose --features "$FEATURES" + +cargo build --release --verbose --features "$FEATURES" +cargo test --release --verbose --features "$FEATURES" + cargo test --manifest-path=ndarray-rand/Cargo.toml --no-default-features --verbose +cargo test --release --manifest-path=ndarray-rand/Cargo.toml --no-default-features --verbose + cargo test --manifest-path=ndarray-rand/Cargo.toml --features quickcheck --verbose +cargo test --release --manifest-path=ndarray-rand/Cargo.toml --features quickcheck --verbose + cargo test --manifest-path=xtest-serialization/Cargo.toml --verbose +cargo test --release --manifest-path=xtest-serialization/Cargo.toml --verbose + cargo test --manifest-path=xtest-blas/Cargo.toml --verbose --features openblas-system +cargo test --release --manifest-path=xtest-blas/Cargo.toml --verbose --features openblas-system + cargo test --examples +cargo test --release --examples + cargo test --manifest-path=xtest-numeric/Cargo.toml --verbose +cargo test --release --manifest-path=xtest-numeric/Cargo.toml --verbose + cargo test --manifest-path=xtest-numeric/Cargo.toml --verbose --features test_blas +cargo test --release --manifest-path=xtest-numeric/Cargo.toml --verbose --features test_blas + ([ "$CHANNEL" != "nightly" ] || cargo bench --no-run --verbose --features "$FEATURES") diff --git a/src/arrayformat.rs b/src/arrayformat.rs index 202805604..7089c48c7 100644 --- a/src/arrayformat.rs +++ b/src/arrayformat.rs @@ -5,7 +5,7 @@ // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. -use super::{ArrayBase, ArrayView, Axis, Data, Dimension, NdProducer}; +use super::{ArrayBase, ArrayView, Axis, Data, Device, Dimension, NdProducer}; use crate::aliases::{Ix1, IxDyn}; use alloc::format; use std::fmt; @@ -122,6 +122,7 @@ where { // Cast into a dynamically dimensioned view // This is required to be able to use `index_axis` for the recursive case + assert_eq!(array.device(), Device::Host, "Cannot print an array that is not on the Host."); format_array_inner(array.view().into_dyn(), f, format, fmt_opt, 0, array.ndim()) } diff --git a/src/data_repr.rs b/src/data_repr.rs index c64cbcfcf..cb57d81f3 100644 --- a/src/data_repr.rs +++ b/src/data_repr.rs @@ -1,3 +1,5 @@ +#![warn(clippy::pedantic, clippy::nursery)] + use crate::extension::nonnull; #[cfg(not(feature = "std"))] use alloc::borrow::ToOwned; @@ -10,6 +12,16 @@ use std::ptr::NonNull; use rawpointer::PointerExt; +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum Device +{ + Host, + #[cfg(feature = "opencl")] + OpenCL, + #[cfg(feature = "cuda")] + CUDA, +} + /// Array's representation. /// /// *Don’t use this type directly—use the type alias @@ -25,6 +37,7 @@ pub struct OwnedRepr ptr: NonNull, len: usize, capacity: usize, + device: Device, } impl OwnedRepr @@ -35,40 +48,239 @@ impl OwnedRepr let len = v.len(); let capacity = v.capacity(); let ptr = nonnull::nonnull_from_vec_data(&mut v); - Self { ptr, len, capacity } + let device = Device::Host; + Self { + ptr, + len, + capacity, + device, + } + } + + pub(crate) const fn device(&self) -> Device + { + self.device + } + + pub(crate) const unsafe fn from_components(ptr: NonNull, len: usize, capacity: usize, device: Device) -> Self + { + Self { + ptr, + len, + capacity, + device, + } + } + + /// Move this storage object to a specified device. + #[allow(clippy::unnecessary_wraps)] + pub(crate) fn move_to_device(self, device: Device) -> Option + { + // println!("Copying to {device:?}"); + // let mut self_ = ManuallyDrop::new(self); + // self_.device = device; + + match (self.device, device) { + (Device::Host, Device::Host) => { + // println!("Copying to Host"); + Some(self) + } + + #[cfg(feature = "opencl")] + (Device::Host, Device::OpenCL) => { + let len = self.len; + let capacity = self.capacity; + let bytes = std::mem::size_of::() * capacity; + + unsafe { + if let Ok(buffer) = + hasty_::opencl::opencl_allocate(bytes, hasty_::opencl::OpenCLMemoryType::ReadWrite) + { + // println!("Allocated OpenCL Buffer"); + if let Ok(_) = + hasty_::opencl::opencl_write(buffer, self.ptr.as_ptr() as *const std::ffi::c_void, bytes) + { + // println!("Wrote to OpenCL Buffer"); + + Some(Self { + ptr: NonNull::new(buffer as *mut A)?, + len, + capacity, + device, + }) + } else { + // println!("Failed to write to OpenCL Buffer"); + None + } + } else { + // println!("Failed to allocate OpenCL Buffer"); + None + } + } + } + + #[cfg(feature = "opencl")] + (Device::OpenCL, Device::Host) => { + let len = self.len; + let capacity = self.capacity; + let bytes = std::mem::size_of::() * capacity; + + unsafe { + let mut data = ManuallyDrop::new(Vec::::with_capacity(self.capacity)); + data.set_len(self.len); + if let Ok(_) = hasty_::opencl::opencl_read( + data.as_mut_ptr() as *mut std::ffi::c_void, + self.ptr.as_ptr() as *mut std::ffi::c_void, + bytes, + ) { + Some(Self { + ptr: nonnull::nonnull_from_vec_data(&mut data), + len, + capacity, + device, + }) + } else { + None + } + } + } + + #[cfg(feature = "opencl")] + (Device::OpenCL, Device::OpenCL) => { + todo!(); + } + + #[cfg(feature = "cuda")] + (Device::Host, Device::CUDA) => { + todo!(); + } + + #[cfg(feature = "cuda")] + (Device::CUDA, Device::Host) => { + todo!(); + } + + #[cfg(feature = "cuda")] + (Device::CUDA, Device::CUDA) => { + todo!(); + } + + #[cfg(all(feature = "opencl", feature = "cuda"))] + (Device::OpenCL, Device::CUDA) => { + todo!(); + } + + #[cfg(all(feature = "opencl", feature = "cuda"))] + (Device::CUDA, Device::OpenCL) => { + todo!(); + } + } + } + + /// Drop the object and free the memory + pub(crate) unsafe fn drop_impl(&mut self) -> Vec + { + let capacity = self.capacity; + let len = self.len; + self.len = 0; + self.capacity = 0; + let ptr = self.ptr.as_ptr(); + + match self.device { + Device::Host => { + // println!("Dropping Host pointer"); + Vec::from_raw_parts(ptr, len, capacity) + } + + #[cfg(feature = "opencl")] + Device::OpenCL => { + // Free `ptr` + // println!("Freeing OpenCL pointer"); + + hasty_::opencl::opencl_free(ptr as *mut std::ffi::c_void); + + // Should be optimised out, since nothing is allocated + Vec::new() + } + + #[cfg(feature = "cuda")] + Device::CUDA => { + // Free `ptr` + println!("Freeing CUDA pointer"); + Vec::new() + } + } } + /// Convert `self` into a [Vec]. + /// + /// # Panics + /// Will panic if the underlying memory is not allocated on + /// the host device. pub(crate) fn into_vec(self) -> Vec { + // Creating a Vec requires the data to be on the host device + assert_eq!(self.device, Device::Host); ManuallyDrop::new(self).take_as_vec() } + /// Get a slice representation of `self`. + /// + /// # Panics + /// Will panic if the underlying memory is not allocated + /// on the host device. pub(crate) fn as_slice(&self) -> &[A] { + // Cannot create a slice of a device pointer + debug_assert_eq!(self.device, Device::Host, "Cannot create a slice of a device pointer"); + unsafe { slice::from_raw_parts(self.ptr.as_ptr(), self.len) } } - pub(crate) fn len(&self) -> usize + pub(crate) const fn len(&self) -> usize { self.len } - pub(crate) fn as_ptr(&self) -> *const A + /// Extract the raw underlying pointer from this object. + /// + /// ## Safety + /// The pointer **may not necessarily point to the host**. + /// Using a non-host pointer on the host will almost certainly + /// cause a segmentation-fault. + pub(crate) const fn as_ptr(&self) -> *const A { self.ptr.as_ptr() } - pub(crate) fn as_ptr_mut(&self) -> *mut A + /// Extract the raw underlying pointer from this object as mut + /// + /// ## Safety + /// The pointer **may not necessarily point to the host**. + /// Using a non-host pointer on the host will almost certainly + /// cause a segmentation-fault. + pub(crate) const fn as_ptr_mut(&self) -> *mut A { self.ptr.as_ptr() } + /// Return underlying [`NonNull`] ptr. + /// + /// ## Safety + /// The pointer **may not necessarily point to the host**. + /// Using a non-host pointer on the host will almost certainly + /// cause a segmentation-fault. pub(crate) fn as_nonnull_mut(&mut self) -> NonNull { self.ptr } /// Return end pointer + /// + /// ## Safety + /// The pointer **may not necessarily point to the host**. + /// Using a non-host pointer on the host will almost certainly + /// cause a segmentation-fault. pub(crate) fn as_end_nonnull(&self) -> NonNull { unsafe { self.ptr.add(self.len) } @@ -77,7 +289,6 @@ impl OwnedRepr /// Reserve `additional` elements; return the new pointer /// /// ## Safety - /// /// Note that existing pointers into the data are invalidated #[must_use = "must use new pointer to update existing pointers"] pub(crate) fn reserve(&mut self, additional: usize) -> NonNull @@ -92,7 +303,6 @@ impl OwnedRepr /// Set the valid length of the data /// /// ## Safety - /// /// The first `new_len` elements of the data should be valid. pub(crate) unsafe fn set_len(&mut self, new_len: usize) { @@ -100,7 +310,10 @@ impl OwnedRepr self.len = new_len; } - /// Return the length (number of elements in total) + /// Return the length (number of elements in total) and set + /// the internal length to zero. + /// + /// todo: Is this valid/safe? Mark as unsafe? pub(crate) fn release_all_elements(&mut self) -> usize { let ret = self.len; @@ -111,7 +324,6 @@ impl OwnedRepr /// Cast self into equivalent repr of other element type /// /// ## Safety - /// /// Caller must ensure the two types have the same representation. /// **Panics** if sizes don't match (which is not a sufficient check). pub(crate) unsafe fn data_subst(self) -> OwnedRepr @@ -123,17 +335,25 @@ impl OwnedRepr ptr: self_.ptr.cast::(), len: self_.len, capacity: self_.capacity, + device: self_.device, } } + /// Apply a `f(Vec) -> Vec` to this storage object and update `self`. fn modify_as_vec(&mut self, f: impl FnOnce(Vec) -> Vec) { let v = self.take_as_vec(); *self = Self::from(f(v)); } + /// Take `self` as a `Vec` object. This invalidates `self`. + /// + /// # Panics + /// Will panic if the underlying memory is not allocated + /// on the host device. fn take_as_vec(&mut self) -> Vec { + assert_eq!(self.device, Device::Host); let capacity = self.capacity; let len = self.len; self.len = 0; @@ -147,21 +367,96 @@ where A: Clone { fn clone(&self) -> Self { - Self::from(self.as_slice().to_owned()) + match self.device { + Device::Host => Self::from(self.as_slice().to_owned()), + + #[cfg(feature = "opencl")] + Device::OpenCL => { + println!("Performing OpenCL Clone"); + unsafe { + // Allocate new buffer + let bytes = std::mem::size_of::() * self.len(); + + match hasty_::opencl::opencl_allocate(bytes, hasty_::opencl::OpenCLMemoryType::ReadWrite) { + Ok(buffer_ptr) => { + if let Err(err_code) = + hasty_::opencl::opencl_copy(buffer_ptr, self.as_ptr() as *const std::ffi::c_void, bytes) + { + panic!("Failed to copy to OpenCL buffer. Exited with status: {:?}", err_code); + } + + Self { + ptr: NonNull::new(buffer_ptr as *mut A).unwrap(), + len: self.len, + capacity: self.capacity, + device: self.device, + } + } + + Err(err_code) => { + panic!("Failed to clone OpenCL buffer. Exited with status: {:?}", err_code); + } + } + } + } + + #[cfg(feature = "cuda")] + Device::CUDA => { + println!("Performing CUDA Clone"); + // todo: CUDA clone + Self::from(self.as_slice().to_owned()) + } + } } fn clone_from(&mut self, other: &Self) { - let mut v = self.take_as_vec(); - let other = other.as_slice(); + match self.device { + Device::Host => { + let mut v = self.take_as_vec(); + let other = other.as_slice(); + + if v.len() > other.len() { + v.truncate(other.len()); + } + let (front, back) = other.split_at(v.len()); + v.clone_from_slice(front); + v.extend_from_slice(back); + *self = Self::from(v); + } - if v.len() > other.len() { - v.truncate(other.len()); + #[cfg(feature = "opencl")] + Device::OpenCL => { + println!("Performing OpenCL Clone From"); + // todo: OpenCL clone from + let mut v = self.take_as_vec(); + let other = other.as_slice(); + + if v.len() > other.len() { + v.truncate(other.len()); + } + let (front, back) = other.split_at(v.len()); + v.clone_from_slice(front); + v.extend_from_slice(back); + *self = Self::from(v); + } + + #[cfg(feature = "cuda")] + Device::CUDA => { + println!("Performing CUDA Clone From"); + // todo: CUDA clone from + let mut v = self.take_as_vec(); + let other = other.as_slice(); + + if v.len() > other.len() { + v.truncate(other.len()); + } + let (front, back) = other.split_at(v.len()); + v.clone_from_slice(front); + v.extend_from_slice(back); + *self = Self::from(v); + } } - let (front, back) = other.split_at(v.len()); - v.clone_from_slice(front); - v.extend_from_slice(back); - *self = Self::from(v); } } @@ -183,7 +478,7 @@ impl Drop for OwnedRepr self.len = 0; } // drop as a Vec. - self.take_as_vec(); + unsafe { self.drop_impl() }; } } } diff --git a/src/data_traits.rs b/src/data_traits.rs index a2784b8d3..93cb7e34d 100644 --- a/src/data_traits.rs +++ b/src/data_traits.rs @@ -8,8 +8,6 @@ //! The data (inner representation) traits for ndarray -use rawpointer::PointerExt; - use alloc::sync::Arc; #[cfg(not(feature = "std"))] use alloc::vec::Vec; @@ -17,7 +15,9 @@ use std::mem::MaybeUninit; use std::mem::{self, size_of}; use std::ptr::NonNull; -use crate::{ArcArray, Array, ArrayBase, CowRepr, Dimension, OwnedArcRepr, OwnedRepr, RawViewRepr, ViewRepr}; +use rawpointer::PointerExt; + +use crate::{ArcArray, Array, ArrayBase, CowRepr, Device, Dimension, OwnedArcRepr, OwnedRepr, RawViewRepr, ViewRepr}; /// Array representation trait. /// @@ -42,6 +42,12 @@ pub unsafe trait RawData: Sized #[doc(hidden)] fn _is_pointer_inbounds(&self, ptr: *const Self::Elem) -> bool; + #[doc(hidden)] + fn _device(&self) -> Option + { + None + } + private_decl! {} } @@ -354,10 +360,21 @@ unsafe impl RawData for OwnedRepr fn _is_pointer_inbounds(&self, self_ptr: *const Self::Elem) -> bool { - let slc = self.as_slice(); - let ptr = slc.as_ptr() as *mut A; - let end = unsafe { ptr.add(slc.len()) }; - self_ptr >= ptr && self_ptr <= end + // let slc = self.as_slice(); + // let ptr = slc.as_ptr() as *mut A; + // let end = unsafe { ptr.add(slc.len()) }; + // self_ptr >= ptr && self_ptr <= end + + // Instead of using a slice, we just get the raw pointer. This assumes that `self.len()` + // is correct, but since this is internally managed, it's safe to assume it is + let ptr = self.as_ptr(); + let end = unsafe { ptr.add(self.len()) }; + ptr <= self_ptr && self_ptr <= end + } + + fn _device(&self) -> Option + { + Some(self.device()) } private_impl! {} diff --git a/src/impl_constructors.rs b/src/impl_constructors.rs index e5f19a837..cdce67e4c 100644 --- a/src/impl_constructors.rs +++ b/src/impl_constructors.rs @@ -625,6 +625,16 @@ where array } + pub(crate) const unsafe fn from_parts(data: S, ptr: std::ptr::NonNull, dim: D, strides: D) -> Self + { + Self { + data, + ptr, + dim, + strides, + } + } + #[deprecated( note = "This method is hard to use correctly. Use `uninit` instead.", since = "0.15.0" diff --git a/src/impl_methods.rs b/src/impl_methods.rs index d1250ec28..17720ccbc 100644 --- a/src/impl_methods.rs +++ b/src/impl_methods.rs @@ -16,6 +16,7 @@ use std::mem::{size_of, ManuallyDrop}; use crate::imp_prelude::*; use crate::argument_traits::AssignElem; +use crate::data_repr::{Device, OwnedRepr}; use crate::dimension; use crate::dimension::broadcast::co_broadcast; use crate::dimension::reshape_dim; @@ -122,6 +123,11 @@ where self.dim.clone() } + pub fn raw_strides(&self) -> D + { + self.strides.clone() + } + /// Return the shape of the array as a slice. /// /// Note that you probably don't want to use this to create an array of the @@ -3045,6 +3051,13 @@ where f(&*prev, &mut *curr) }); } + + pub fn device(&self) -> Device + { + // If a device is returned, use that. Otherwise, it's fairly safe to + // assume that the data is on the host. + self.data._device().unwrap_or(Device::Host) + } } /// Transmute from A to B. @@ -3064,3 +3077,26 @@ unsafe fn unlimited_transmute(data: A) -> B } type DimMaxOf = >::Output; + +impl ArrayBase, D> +// where A: std::fmt::Debug +{ + // pub fn device(&self) -> Device { + // self.data.device() + // } + + pub fn move_to_device(self, device: Device) -> Option + { + let dim = self.dim; + let strides = self.strides; + let data = self.data.move_to_device(device)?; + let ptr = std::ptr::NonNull::new(data.as_ptr() as *mut A).unwrap(); + + Some(Self { + data, + ptr, + dim, + strides, + }) + } +} diff --git a/src/impl_ops.rs b/src/impl_ops.rs index 46ea18a7c..8d1798080 100644 --- a/src/impl_ops.rs +++ b/src/impl_ops.rs @@ -7,6 +7,9 @@ // except according to those terms. use crate::dimension::DimMax; +use crate::Device; +use crate::Layout; +use crate::OwnedRepr; use crate::Zip; use num_complex::Complex; @@ -50,10 +53,28 @@ impl ScalarOperand for f64 {} impl ScalarOperand for Complex {} impl ScalarOperand for Complex {} +macro_rules! device_check_assert( + ($self:expr, $rhs:expr) => { + debug_assert_eq!($self.device(), $rhs.device(), + "Cannot perform operation on arrays on different devices. \ + Please move them to the same device first."); + } +); + +// Pick the expression $a for commutative and $b for ordered binop +macro_rules! if_commutative { + (Commute { $a:expr } or { $b:expr }) => { + $a + }; + (Ordered { $a:expr } or { $b:expr }) => { + $b + }; +} + macro_rules! impl_binary_op( - ($trt:ident, $operator:tt, $mth:ident, $iop:tt, $doc:expr) => ( + ($rs_trait:ident, $operator:tt, $math_op:ident, $inplace_op:tt, $docstring:expr) => ( /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between `self` and `rhs`, /// and return the result. /// @@ -62,9 +83,9 @@ macro_rules! impl_binary_op( /// If their shapes disagree, `self` is broadcast to their broadcast shape. /// /// **Panics** if broadcasting isn’t possible. -impl $trt> for ArrayBase +impl $rs_trait> for ArrayBase where - A: Clone + $trt, + A: Clone + $rs_trait, B: Clone, S: DataOwned + DataMut, S2: Data, @@ -73,14 +94,15 @@ where { type Output = ArrayBase>::Output>; #[track_caller] - fn $mth(self, rhs: ArrayBase) -> Self::Output + fn $math_op(self, rhs: ArrayBase) -> Self::Output { - self.$mth(&rhs) + device_check_assert!(self, rhs); + self.$math_op(&rhs) } } /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between `self` and reference `rhs`, /// and return the result. /// @@ -90,9 +112,9 @@ where /// cloning the data if needed. /// /// **Panics** if broadcasting isn’t possible. -impl<'a, A, B, S, S2, D, E> $trt<&'a ArrayBase> for ArrayBase +impl<'a, A, B, S, S2, D, E> $rs_trait<&'a ArrayBase> for ArrayBase where - A: Clone + $trt, + A: Clone + $rs_trait, B: Clone, S: DataOwned + DataMut, S2: Data, @@ -101,27 +123,29 @@ where { type Output = ArrayBase>::Output>; #[track_caller] - fn $mth(self, rhs: &ArrayBase) -> Self::Output + fn $math_op(self, rhs: &ArrayBase) -> Self::Output { + device_check_assert!(self, rhs); + if self.ndim() == rhs.ndim() && self.shape() == rhs.shape() { let mut out = self.into_dimensionality::<>::Output>().unwrap(); - out.zip_mut_with_same_shape(rhs, clone_iopf(A::$mth)); + out.zip_mut_with_same_shape(rhs, clone_iopf(A::$math_op)); out } else { let (lhs_view, rhs_view) = self.broadcast_with(&rhs).unwrap(); if lhs_view.shape() == self.shape() { let mut out = self.into_dimensionality::<>::Output>().unwrap(); - out.zip_mut_with_same_shape(&rhs_view, clone_iopf(A::$mth)); + out.zip_mut_with_same_shape(&rhs_view, clone_iopf(A::$math_op)); out } else { - Zip::from(&lhs_view).and(&rhs_view).map_collect_owned(clone_opf(A::$mth)) + Zip::from(&lhs_view).and(&rhs_view).map_collect_owned(clone_opf(A::$math_op)) } } } } /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between reference `self` and `rhs`, /// and return the result. /// @@ -131,9 +155,9 @@ where /// cloning the data if needed. /// /// **Panics** if broadcasting isn’t possible. -impl<'a, A, B, S, S2, D, E> $trt> for &'a ArrayBase +impl<'a, A, B, S, S2, D, E> $rs_trait> for &'a ArrayBase where - A: Clone + $trt, + A: Clone + $rs_trait, B: Clone, S: Data, S2: DataOwned + DataMut, @@ -142,28 +166,30 @@ where { type Output = ArrayBase>::Output>; #[track_caller] - fn $mth(self, rhs: ArrayBase) -> Self::Output - where + fn $math_op(self, rhs: ArrayBase) -> Self::Output + // where { + device_check_assert!(self, rhs); + if self.ndim() == rhs.ndim() && self.shape() == rhs.shape() { let mut out = rhs.into_dimensionality::<>::Output>().unwrap(); - out.zip_mut_with_same_shape(self, clone_iopf_rev(A::$mth)); + out.zip_mut_with_same_shape(self, clone_iopf_rev(A::$math_op)); out } else { let (rhs_view, lhs_view) = rhs.broadcast_with(self).unwrap(); if rhs_view.shape() == rhs.shape() { let mut out = rhs.into_dimensionality::<>::Output>().unwrap(); - out.zip_mut_with_same_shape(&lhs_view, clone_iopf_rev(A::$mth)); + out.zip_mut_with_same_shape(&lhs_view, clone_iopf_rev(A::$math_op)); out } else { - Zip::from(&lhs_view).and(&rhs_view).map_collect_owned(clone_opf(A::$mth)) + Zip::from(&lhs_view).and(&rhs_view).map_collect_owned(clone_opf(A::$math_op)) } } } } /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between references `self` and `rhs`, /// and return the result as a new `Array`. /// @@ -171,9 +197,9 @@ where /// cloning the data if needed. /// /// **Panics** if broadcasting isn’t possible. -impl<'a, A, B, S, S2, D, E> $trt<&'a ArrayBase> for &'a ArrayBase +impl<'a, A, B, S, S2, D, E> $rs_trait<&'a ArrayBase> for &'a ArrayBase where - A: Clone + $trt, + A: Clone + $rs_trait + std::fmt::Debug, B: Clone, S: Data, S2: Data, @@ -182,7 +208,9 @@ where { type Output = Array>::Output>; #[track_caller] - fn $mth(self, rhs: &'a ArrayBase) -> Self::Output { + fn $math_op(self, rhs: &'a ArrayBase) -> Self::Output { + device_check_assert!(self, rhs); + let (lhs, rhs) = if self.ndim() == rhs.ndim() && self.shape() == rhs.shape() { let lhs = self.view().into_dimensionality::<>::Output>().unwrap(); let rhs = rhs.view().into_dimensionality::<>::Output>().unwrap(); @@ -190,24 +218,115 @@ where } else { self.broadcast_with(rhs).unwrap() }; - Zip::from(lhs).and(rhs).map_collect(clone_opf(A::$mth)) + + match self.device() { + Device::Host => { + Zip::from(lhs).and(rhs).map_collect(clone_opf(A::$math_op)) + } + + #[cfg(feature = "opencl")] + Device::OpenCL => { + if lhs.raw_dim().ndim() == 0 && rhs.raw_dim().ndim() == 0 { + // println!("Scalar"); + todo!(); + } else if lhs.layout_impl().is(Layout::CORDER | Layout::FORDER) && + rhs.layout_impl().is(Layout::CORDER | Layout::FORDER) && + lhs.layout_impl().matches(rhs.layout_impl()) { + // println!("Contiguous"); + + static mut KERNEL_BUILT: bool = false; // todo: fix monomorphization issue + + let typename = match crate::opencl::rust_type_to_c_name::() { + Some(x) => x, + None => panic!("The Rust type {} is not supported by the \ + OpenCL backend", std::any::type_name::()) + }; + + let kernel_name = format!("binary_op_{}_{}", stringify!($math_op), typename); + + if unsafe { !KERNEL_BUILT } { + let kernel = crate::opencl::gen_contiguous_linear_kernel_3( + &kernel_name, + typename, + stringify!($operator)); + + unsafe { + if let Err(e) = hasty_::opencl::opencl_add_kernel(&kernel) { + panic!("Failed to add OpenCL kernel. Errored with code {:?}", e); + } + KERNEL_BUILT = true; + } + } + + unsafe { + let elements = self.len(); + let self_ptr = self.as_ptr() as *mut std::ffi::c_void; + let other_ptr = rhs.as_ptr() as *mut std::ffi::c_void; + let res_ptr = match hasty_::opencl::opencl_allocate( + elements * std::mem::size_of::(), + hasty_::opencl::OpenCLMemoryType::ReadWrite + ) { + Ok(buf) => buf, + Err(e) => panic!("Failed to allocate OpenCL buffer. Exited with: {:?}", e) + }; + + match hasty_::opencl::opencl_run_contiguous_linear_kernel_3( + &kernel_name, + elements, + self_ptr, + other_ptr, + res_ptr, + ) { + Ok(()) => { + use std::ptr::NonNull; + + let ptr = NonNull::new(res_ptr as *mut A).unwrap(); + let data = OwnedRepr::::from_components( + ptr, + self.len(), + self.len(), + self.device(), + ); + + Self::Output::from_parts( + data, + ptr, + >::Output::from_dimension(&self.raw_dim()).unwrap(), + >::Output::from_dimension(&self.raw_strides()).unwrap(), + ) + } + Err(e) => panic!("Failed to run OpenCL kernel '{}'. \ + Exited with code: {:?}", kernel_name, e), + } + } + } else { + println!("Strided"); + todo!(); + } + } + + #[cfg(feature = "cuda")] + Device::CUDA => { + todo!(); + } + } } } /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between `self` and the scalar `x`, /// and return the result (based on `self`). /// /// `self` must be an `Array` or `ArcArray`. -impl $trt for ArrayBase - where A: Clone + $trt, +impl $rs_trait for ArrayBase + where A: Clone + $rs_trait, S: DataOwned + DataMut, D: Dimension, B: ScalarOperand, { type Output = ArrayBase; - fn $mth(mut self, x: B) -> ArrayBase { + fn $math_op(mut self, x: B) -> ArrayBase { self.map_inplace(move |elt| { *elt = elt.clone() $operator x.clone(); }); @@ -216,33 +335,23 @@ impl $trt for ArrayBase } /// Perform elementwise -#[doc=$doc] +#[doc=$docstring] /// between the reference `self` and the scalar `x`, /// and return the result as a new `Array`. -impl<'a, A, S, D, B> $trt for &'a ArrayBase - where A: Clone + $trt, +impl<'a, A, S, D, B> $rs_trait for &'a ArrayBase + where A: Clone + $rs_trait, S: Data, D: Dimension, B: ScalarOperand, { type Output = Array; - fn $mth(self, x: B) -> Self::Output { + fn $math_op(self, x: B) -> Self::Output { self.map(move |elt| elt.clone() $operator x.clone()) } } ); ); -// Pick the expression $a for commutative and $b for ordered binop -macro_rules! if_commutative { - (Commute { $a:expr } or { $b:expr }) => { - $a - }; - (Ordered { $a:expr } or { $b:expr }) => { - $b - }; -} - macro_rules! impl_scalar_lhs_op { // $commutative flag. Reuse the self + scalar impl if we can. // We can do this safely since these are the primitive numeric types @@ -290,10 +399,11 @@ impl<'a, S, D> $trt<&'a ArrayBase> for $scalar mod arithmetic_ops { - use super::*; + use std::ops::*; + use crate::imp_prelude::*; - use std::ops::*; + use super::*; fn clone_opf(f: impl Fn(A, B) -> C) -> impl FnMut(&A, &B) -> C { @@ -441,9 +551,10 @@ mod arithmetic_ops mod assign_ops { - use super::*; use crate::imp_prelude::*; + use super::*; + macro_rules! impl_assign_op { ($trt:ident, $method:ident, $doc:expr) => { use std::ops::$trt; diff --git a/src/layout/mod.rs b/src/layout/mod.rs index 026688d63..f0e759b51 100644 --- a/src/layout/mod.rs +++ b/src/layout/mod.rs @@ -79,6 +79,21 @@ impl Layout (self.is(Layout::CORDER) as i32 - self.is(Layout::FORDER) as i32) + (self.is(Layout::CPREFER) as i32 - self.is(Layout::FPREFER) as i32) } + + /// Return true if the layout order of `self` matches the layout order of `other` + /// + /// **Note**: We ignore the preference bits + #[inline(always)] + pub(crate) fn matches(self, other: Self) -> bool + { + self.0 & (0b11) == other.0 & (0b11) + } + + // /// Return true if this layout exactly matches the other layout + // #[inline(always)] + // pub(crate) fn matches_exact(self, other: Self) -> bool { + // self.0 == other.0 + // } } #[cfg(test)] diff --git a/src/lib.rs b/src/lib.rs index 37af0adfe..569e298e5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -208,6 +208,7 @@ mod dimension; pub use crate::zip::{FoldWhile, IntoNdProducer, NdProducer, Zip}; +pub use crate::data_repr::Device; pub use crate::layout::Layout; /// Implementation's prelude. Common types used everywhere. @@ -1129,7 +1130,7 @@ pub type Ixs = isize; /// } /// let arr = Array2::from_shape_vec((nrows, ncols), data)?; /// assert_eq!(arr, array![[0, 0, 0], [1, 1, 1]]); -/// # Ok::<(), ndarray::ShapeError>(()) +/// Ok::<(), ndarray::ShapeError>(()) /// ``` /// /// If neither of these options works for you, and you really need to convert @@ -1153,7 +1154,7 @@ pub type Ixs = isize; /// [[1, 2, 3], [4, 5, 6]], /// [[7, 8, 9], [10, 11, 12]], /// ]); -/// # Ok::<(), ndarray::ShapeError>(()) +/// Ok::<(), ndarray::ShapeError>(()) /// ``` /// /// Note that this implementation assumes that the nested `Vec`s are all the @@ -1617,3 +1618,14 @@ pub(crate) fn is_aligned(ptr: *const T) -> bool { (ptr as usize) % ::std::mem::align_of::() == 0 } + +#[cfg(feature = "opencl")] +mod opencl; + +pub fn configure() +{ + #[cfg(feature = "opencl")] + unsafe { + hasty_::opencl::configure_opencl(); + } +} diff --git a/src/opencl.rs b/src/opencl.rs new file mode 100644 index 000000000..6e5206dcc --- /dev/null +++ b/src/opencl.rs @@ -0,0 +1,46 @@ +pub(crate) fn rust_type_to_c_name() -> Option<&'static str> +{ + match std::any::type_name::() { + "f32" => Some("float"), + "f64" => Some("double"), + "i8" => Some("int8_t"), + "i16" => Some("int16_t"), + "i32" => Some("int32_t"), + "i64" => Some("int64_t"), + "u8" => Some("uint8_t"), + "u16" => Some("uint16_t"), + "u32" => Some("uint32_t"), + "u64" | "usize" => Some("uint64_t"), + _ => None, + } +} + +pub(crate) fn gen_contiguous_linear_kernel_3(kernel_name: &str, typename: &str, op: &str) -> String +{ + format!( + r#" + #ifndef NDARRAY_INCLUDE_STDINT + #define NDARRAY_INCLUDE_STDINT + + // We should probably verify that these are, in fact, correct + typedef char int8_t; + typedef short int16_t; + typedef int int32_t; + typedef long int64_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; + typedef unsigned long uint64_t; + #endif // NDARRAY_INCLUDE_STDINT + + __kernel void {kernel_name}(__global const {typename} *a, __global const {typename} *b, __global {typename} *c) {{ + // Get id as 64-bit integer to avoid overflow + uint64_t i = get_global_id(0); + c[i] = a[i] {op} b[i]; + }} + "#, + kernel_name = kernel_name, + typename = typename, + op = op, + ) +}