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, + ) +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy

Alternative Proxy