Merge remote-tracking branch 'upstream/dev' into rot-interp

This commit is contained in:
Joshua Smith 2024-03-28 20:33:00 -04:00
commit 5a1f9a5236
192 changed files with 9270 additions and 4435 deletions

View File

@ -49,8 +49,6 @@ jobs:
build-nalgebra-all-features:
runs-on: ubuntu-latest
steps:
# Needed because the --all-features build which enables cuda support.
- uses: Jimver/cuda-toolkit@v0.2.4
- uses: actions/checkout@v2
- run: cargo build --all-features;
- run: cargo build -p nalgebra-glm --all-features;
@ -61,7 +59,7 @@ jobs:
steps:
- uses: actions/checkout@v2
- name: test
run: cargo test --features arbitrary,rand,serde-serialize,sparse,debug,io,compare,libm,proptest-support,slow-tests;
run: cargo test --features arbitrary,rand,serde-serialize,sparse,debug,io,compare,libm,proptest-support,slow-tests,rkyv-safe-deser,rayon;
test-nalgebra-glm:
runs-on: ubuntu-latest
steps:
@ -120,20 +118,9 @@ jobs:
run: xargo build --verbose --no-default-features -p nalgebra-glm --target=x86_64-unknown-linux-gnu;
- name: build thumbv7em-none-eabihf nalgebra-glm
run: xargo build --verbose --no-default-features -p nalgebra-glm --target=thumbv7em-none-eabihf;
build-cuda:
docs:
runs-on: ubuntu-latest
steps:
- uses: Jimver/cuda-toolkit@v0.2.4
with:
cuda: '11.2.2'
- name: Install nightly-2021-12-04
uses: actions-rs/toolchain@v1
with:
toolchain: nightly-2021-12-04
override: true
- uses: actions/checkout@v2
- run: rustup target add nvptx64-nvidia-cuda
- run: cargo build --no-default-features --features cuda
- run: cargo build --no-default-features --features cuda --target=nvptx64-nvidia-cuda
env:
CUDA_ARCH: "350"
- name: Generate documentation
run: cargo doc

View File

@ -1,16 +1,170 @@
# Change Log
All notable changes to `nalgebra`, starting with the version 0.6.0 will be
documented here.
This project adheres to [Semantic Versioning](https://semver.org/).
## [0.30.1] (09 Jan. 2022)
## Unreleased
### Removed
- The `cuda` feature has been removed, as the toolchain it depends on
is long abandoned.
## [0.32.5] (28 March 2024)
## Fixed
- Fix numerical issue on SVD with near-identity matrix.
## [0.32.4] (19 Feb 2023)
### Added
- Add the `glam-0.25` feature to enable conversion from/to types from `glam` v0.25.
## [0.32.3] (09 July 2023)
### Modified
- Statically sized matrices are now serialized as tuples to match how serde
serialized plain arrays.
- Dont require `Scalar` for matrix `PartialEq` and `Eq`.
### Added
- Allow trailing punctuation in macros `vector!`, `matrix!`, `point!`, etc.
- Add the methods `Matrix1::as_scalar`, `::as_scalar_mut`, `::to_scalar`, `::into_scalar`.
- Add `Rotation3::euler_angles_ordered`, a generalized euler angles calculation.
- Add the `glam-0.24` feature to enable conversion from/to types from `glam` v0.24.
- Add the `glam-0.25` feature to enable conversion from/to types from `glam` v0.25.
- Add the `lerp` method to points.
- Implement `Clone` for `MatrixIter`.
### Fixed
- Fixed severe catastrophic cancellation issue in variance calculation.
## [0.32.2] (07 March 2023)
### Added
- Add the `glam-0.23` to enable conversion from/to type from `glam` v0.23.
## [0.32.1] (14 Jan. 2023)
### Modified
- Updated `nalgebra-macros` to use the new `Dyn`, avoiding macro-generated deprecation warnings.
## [0.32.0] (14 Jan. 2023)
### Modified
- Renamed all `MatrixSlice` types to `MatrixView`. In general all occurrences of the world `Slice` or `slice` have been
replaced by `View` or `view`.
- Deprecated all the types involving `Slice` in its name, in favor of the word `View`.
- Make it so that most `nalgebra` objects archive as themselves (when using `rkyv` for serialization).
- Renamed `Dynamic` to `Dyn` and make `Dyn` a tuple struct.
### Added
- Add `Cholesky::ln_determinant` to compute the natural logarithm of the determinant of a matrix decomposed
with Cholesky. This can be more numerically stable than computing the determinant itself when very small and/or
large values are involved.
- Added new methods `Matrix::as_view` and `Matrix::as_view_mut`, which are very useful when working with view-based
APIs.
- Added parallel column iterator using `rayon`: `Matrix::par_column_iter` and `Matrix::par_column_iter_mut`. The `rayon`
feature must be enabled to access these methods.
- Implement `ReshapableStorage` for matrix slices (only for unit strides at the moment).
- Add `U0, U1, …` constants alongside the `U0, U1, …` types. This lets us write `U4` instead of `U4::name()` or
`Const::<4>` when we need const dimensions.
### Fixed
- Fixed the implementation of `Rotation3::euler_angles` to return the angles in the documented order (roll, pitch, yaw).
## [0.31.4] (13 Nov. 2022)
### Added
- Add a `convert-glam022` feature to enable conversion between `nalgebra` and `glam v0.22`.
## [0.31.3] (30 Oct. 2022)
### Added
- Add `Matrix::try_cast` to attempt casting the inner scalar types when that cast may fail.
### Fixed
- Fixed the usage of `CheckBytes` with `rkyv`.
## [0.31.2] (09 Oct. 2022)
### Modified
- Use `#[inline]` on the `Dim` implementation for `Const` to improve opt-level 1 performance.
- Make the `Point::new` constructions const-fn.
### Added
- Add `UnitVector::cast` to change the underlying scalar type.
## [0.31.1] (31 July 2022)
### Modified
- Improve performances of multiplication of two sparse matrices.
### Added
- Add `Matrix::from_row_iterator` to build a matrix from an iterator yielding components in row-major order.
- Add support for conversion from/to types of `glam` 0.21.
- `nalgebra-sparse`: add support for the matrix-market export of sparse matrices.
- `nalgebra-lapack`: add a `GE` for solving the generalized eigenvalues problem.
### Fixed
- Fix `Rotation3::from_matrix` and `UnitQuaternion::from_matrix` when the input matrix is already a valid
rotation matrix.
## [0.31.0] (30 Apr. 2022)
### Breaking changes
- Switch to `cust` 0.3 (for CUDA support).
- Switch to `rkyv` 0.7
- Remove support for serialization based on `abomonation`.
- Remove support for conversions between `nalgebra` types and `glam` 0.13.
### Modified
- The aliases for `Const` types have been simplified to help `rust-analyzer`.
### Added
- Add `TryFrom` conversion between `UnitVector2/3/4` and `glam`s `Vec2/3/4`.
- `nalgebra-sparse`: added support for serialization of sparse matrices with `serde`.
- `nalgebra-sparse`: add a CSC matrix constructor from unsorted (but valid) data.
- `nalgebra-lapack`: add generalized eigenvalues/eigenvectors calculation + QZ decomposition.
### Fixed
- Improve stability of SVD.
- Fix slerp for `UnitComplex`.
## [0.30.1] (09 Jan. 2022)
### Added
- Add conversion from/to types of `glam` 0.19 and 0.20.
## [0.30.0] (02 Jan. 2022)
### Breaking changes
- The `Dim` trait is now marked as unsafe.
- The `Matrix::pow` and `Matrix::pow_mut` methods only allow positive integer exponents now. To compute negative
exponents, the user is free to invert the matrix before calling `pow` with the exponents absolute value.
@ -20,6 +174,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
return `Option<Self>`, meaning that it could be implemented by any type.
### Modified
- Use more concise debug impls for matrices and geometric transformation types.
- The singular values computed by the SVD are now sorted in increasing order by default. Use `SVD::new_unordered`
instead to reproduce the older behavior without the sorting overhead.
@ -29,6 +184,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- The `Matrix::pow` and `Matrix::pow_mut` methods will now also work with integer matrices.
### Added
- Added the conversion trait `From<Vec<T>>` and method `from_vec_storage` for `RowDVector`.
- Added implementation of `From` and `Into` for converting between `nalgebra` types and types from
`glam 0.18`. These can be enabled by enabling the `convert-glam018` cargo features.
@ -49,6 +205,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- `nalgebra-sparse`: added reading MatrixMarked data files to a sparse `CooMatrix`.
### Fixed
- Fixed a potential unsoundness with `matrix.get(i)` and `matrix.get_mut(i)` where `i` is an `usize`, and `matrix`
is a matrix slice with non-default strides.
- Fixed potential unsoundness with `vector.perp` where `vector` isnt actually a 2D vector as expected.
@ -57,9 +214,10 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Fixed the `no-std` build of `nalgebra-glm`.
- Fix the `pow` and `pow_mut` functions (the result was incorrect for some exponent values).
## [0.29.0]
### Breaking changes
- We updated to the version 0.6 of `simba`. This means that the trait bounds `T: na::RealField`, `na::ComplexField`,
`na::SimdRealField`, `na:SimdComplexField` no imply that `T: Copy` (they only imply that `T: Clone`). This may affect
generic code.
@ -71,6 +229,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
way.
### Modified
- `Orthographic3::from_matrix_unchecked` is now `const fn`.
- `Perspective3::from_matrix_unchecked` is now `const fn`.
- `Rotation::from_matrix_unchecked` is now `const fn`.
@ -78,6 +237,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
`Copy` are now much safer to work with thanks to the refactoring of the `Allocator` system.
### Added
- The conversion traits form the `bytemuck` crates are now implemented for the geometric types too.
- Added operator overloading for `Transform * UnitComplex`, `UnitComplex * Transform`, `Transform ×= UnitComplex`,
`Transform ÷= UnitComplex`.
@ -88,16 +248,21 @@ This project adheres to [Semantic Versioning](https://semver.org/).
cargo features.
## [0.28.0]
### Added
- Implement `Hash` for `Transform`.
- Implement `Borrow` and `BorrowMut` for contiguous slices.
### Modified
- The `OPoint<T, D>` type has been added. It takes the dimension number as a type-level integer (e.g. `Const<3>`) instead
- The `OPoint<T, D>` type has been added. It takes the dimension number as a type-level integer (e.g. `Const<3>`)
instead
of a const-generic. The type `Point<T, const D: usize>` is now an alias for `OPoint`. This changes doesn't affect any
of the existing code using `Point`. However, it will allow the use `OPoint` in a generic context where the dimension
cannot be easily expressed as a const-generic (because of the current limitation of const-generics in Rust).
- Several clippy warnings were fixed. This results in some method signature changes (e.g. taking `self` instead of `&self`)
- Several clippy warnings were fixed. This results in some method signature changes (e.g. taking `self` instead
of `&self`)
but this should not have any practical infulances on existing codebase.
- The `Point::new` constructors are no longer const-fn. This is due to some limitations in const-fn
not allowing custom trait-bounds. Use the `point!` macro instead to build points in const environments.
@ -105,30 +270,38 @@ This project adheres to [Semantic Versioning](https://semver.org/).
- Methods returning `Result<(), ()>` now return `bool` instead.
### Fixed
- Fixed a potential unsoundess issue when converting a mutable slice to a `&mut[T]`.
## [0.27.1]
### Fixed
- Fixed a bug in the conversion from `glam::Vec2` or `glam::DVec2` to `Isometry2`.
## [0.27.0]
This removes the `convert-glam` and `convert-glam-unchecked` optional features.
Instead, this adds the `convert-glam013`, `convert-glam014`, and `convert-glam015` optional features for
conversions targeting the versions 0.13, 0.14, and 0.15 of `glam`.
### Added
- Add macros `matrix!`, `dmatrix!`, `vector!`, `dvector!`, `point!` for constructing matrices/vectors/points in a
more convenient way. See [#886](https://github.com/dimforge/nalgebra/pull/886) and [#899](https://github.com/dimforge/nalgebra/pull/899).
more convenient way. See [#886](https://github.com/dimforge/nalgebra/pull/886)
and [#899](https://github.com/dimforge/nalgebra/pull/899).
- Add `CooMatrix::reserve` to `nalgebra-sparse`.
- Add basic support for serialization using `rkyv`. Can be enabled with the features `rkyv-serialize` or
`rkyv-serialize-no-std`.
### Fixed
- Fixed a potential unsoundness issue after deserializing an invalid `DVector` using `serde`.
## [0.26.2]
### Added
- Conversion from an array `[T; D]` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion from a static vector `SVector<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
- Conversion from a point `Point<T; D>` to an isometry `Isometry<T, _, D>` (as a translation).
@ -138,14 +311,17 @@ conversions targeting the versions 0.13, 0.14, and 0.15 of `glam`.
- Conversion of a glam type `Vec2/3/4` from/to a `Translation2/3/4`.
## [0.26.1]
Fix a regression introduced in 0.26.0 preventing `DVector` from being serialized with `serde`.
## [0.26.0]
This release integrates `min-const-generics` to nalgebra. See
[our blog post](https://www.dimforge.com/blog/2021/04/12/integrating-const-generics-to-nalgebra)
for details about this release.
### Added
- Add type aliases for unit vector, e.g., `UnitVector3`.
- Add a `pow` and `pow_mut` function to square matrices.
- Add `Cholesky::determinant` to compute the determinant of a matrix decomposed
@ -153,8 +329,8 @@ for details about this release.
- Add the `serde-serialize-no-std` feature to enable serialization of static matrices/vectors
with serde, but without requiring `std`.
### Modified
- The `serde` crate isn't enabled by default now. Enable the `serde-serialize` or the
`serde-serialize-no-std` features instead.
- The `Const<const D: usize>` type has been introduced to represent dimensions known
@ -176,16 +352,22 @@ for details about this release.
constructor is also a `const fn` now.
## [0.25.4]
### Fixed
- Fix a compilation error when only the `serde-serialize` feature is enabled.
## [0.25.3]
### Added
- The `Vector::simd_cap_magnitude` method to cap the magnitude of the vector with
SIMD components.
## [0.25.2]
### Added
- A `convert-glam` cargo feature to enable implementations of `From` traits to convert
between `glam` types and `nalgebra` types.
- A `convert-glam-unchecked` cargo feature to enable some extra `glam`/`nalgebra` conversions that may
@ -196,56 +378,70 @@ for details about this release.
type of the components of a given entity. Example: `vector.cast::<f32>()`.
## [0.25.1]
This release replaces the version 0.25.0 which has been yanked. The 0.25.0 version
added significant complication to build `nalgebra` targeting a `#[no-std]` platform
not supported by `rand`.
The `rand` dependency is now optional (and disabled by default). You may enable it with:
- The `rand-no-std` cargo feature when targeting a `#[no-std]` environment.
- The `rand` cargo feature when targeting a `std` environment.
## [0.25.0] - Yanked
This updates all the dependencies of nalgebra to their latest version, including:
- rand 0.8
- proptest 1.0
- simba 0.4
### New crate: nalgebra-sparse
Alongside this release of `nalgebra`, we are releasing `nalgebra-sparse`: a crate dedicated to sparse matrix
computation with `nalgebra`. The `sparse` module of `nalgebra`itself still exists for backward compatibility,
but it will be deprecated soon in favor of the `nalgebra-sparse` crate.
### Added
* Add `UnitDualQuaternion`, a dual-quaternion with unit magnitude which can be used as an isometry transformation.
* Add `UDU::new()` and `matrix.udu()` to compute the UDU factorization of a matrix.
* Add `ColPivQR::new()` and `matrix.col_piv_qr()` to compute the QR decomposition with column pivoting of a matrix.
* Add `from_basis_unchecked` to all the rotation types. This builds a rotation from a set of basis vectors (representing the columns of the corresponding rotation matrix).
* Add `from_basis_unchecked` to all the rotation types. This builds a rotation from a set of basis vectors (representing
the columns of the corresponding rotation matrix).
* Add `Matrix::cap_magnitude` to cap the magnitude of a vector.
* Add `UnitQuaternion::append_axisangle_linearized` to approximately append a rotation represented as an axis-angle to a rotation represented as an unit quaternion.
* Add `UnitQuaternion::append_axisangle_linearized` to approximately append a rotation represented as an axis-angle to a
rotation represented as an unit quaternion.
* Mark the iterators on matrix components as `DoubleEndedIter`.
* Re-export `simba::simd::SimdValue` at the root of the `nalgebra` crate.
## [0.24.0]
### Added
* The `DualQuaternion` type. It is still work-in-progress, but the basics are here:
creation from its real and dual part, multiplication of two dual quaternions,
and normalization.
### Removed
* There is no blanket `impl<T> PartialEq for Unit<T>` anymore. Instead, it is
implemented specifically for `UnitComplex`, `UnitQuaternion` and `Unit<Vector>`.
## [0.23.2]
In this release, we improved the documentation of some of the geometric types
by applying changes similar to what we did in the version 0.23.1 for matrices.
### Added
* The `Isometry::inv_mul` method which is a more efficient way of doing
`isometry1.inverse() * isometry2`.
## [0.23.1]
In this release we improved the documentation of the matrix and vector types by:
- Grouping `impl` bocks logically, adding a title comment to these impl blocks.
- Reference these impl blocks docs at the top of the documentation page for `Matrix`.
- Reduce the depth of type aliasing. Now all vector and matrix types are aliases of `Matrix`
@ -254,13 +450,17 @@ In this release we improved the documentation of the matrix and vector types by:
## [0.23.0]
### Added
* The `.inverse_transform_unit_vector(v)` was added to `Rotation2/3`, `Isometry2/3`, `UnitQuaternion`, and `UnitComplex`.
* The `.inverse_transform_unit_vector(v)` was added to `Rotation2/3`, `Isometry2/3`, `UnitQuaternion`,
and `UnitComplex`.
It applies the corresponding rotation to a unit vector `Unit<Vector2/3>`.
* The `Point.map(f)` and `Point.apply(f)` to apply a function to each component of the point, similarly to `Vector.map(f)`
* The `Point.map(f)` and `Point.apply(f)` to apply a function to each component of the point, similarly
to `Vector.map(f)`
and `Vector.apply(f)`.
* The `Quaternion::from([N; 4])` conversion to build a quaternion from an array of four elements.
* The `Isometry::from(Translation)` conversion to build an isometry from a translation.
* The `Vector::ith_axis(i)` which build a unit vector, e.g., `Unit<Vector3<f32>>` with its i-th component set to 1.0, and the
* The `Vector::ith_axis(i)` which build a unit vector, e.g., `Unit<Vector3<f32>>` with its i-th component set to 1.0,
and the
others set to zero.
* The `Isometry.lerp_slerp` and `Isometry.try_lerp_slerp` methods to interpolate between two isometries using linear
interpolation for the translational part, and spherical interpolation for the rotational part.
@ -268,12 +468,14 @@ In this release we improved the documentation of the matrix and vector types by:
spherical interpolation.
## [0.22.0]
In this release, we are using the new version 0.2 of simba. One major change of that version is that the
use of `libm` is now opt-in when building targeting `no-std` environment. If you are using floating-point
operations with nalgebra in a `no-std` environment, you will need to enable the new `libm` feature
of nalgebra for your code to compile again.
### Added
* The `libm` feature that enables `libm` when building for `no-std` environment.
* The `libm-force` feature that enables `libm` even when building for a not `no-std` environment.
* `Cholesky::new_unchecked` which build a Cholesky decomposition without checking that its input is
@ -284,6 +486,7 @@ of nalgebra for your code to compile again.
* The `Vector::ith(i, x)` that builds a vector filled with zeros except for the `i`-th component set to `x`.
## [0.21.0]
In this release, we are no longer relying on traits from the __alga__ crate for our generic code.
Instead, we use traits from the new [simba](https://crates.io/crates/simba) crate which are both
simpler, and allow for significant optimizations like AoSoA SIMD.
@ -292,75 +495,98 @@ Refer to the [monthly dimforge blogpost](https://www.dimforge.org/blog/2020/04/0
for details about this switch and its benefits.
### Added
* It is now possible to use SIMD types like `simba::f32x4` as scalar types for nalgebra's matrices and
geometric types.
### Modified
* Use of traits like `alga::general::{RealField, ComplexField}` have now been replaced by
`simba::scalar::{RealField, ComplexField}`.
* The implementation of traits from the __alga__ crate (and well as the dependency to _alga__) are now
omitted unless the `alga` cargo feature is activated.
### Removed
* The `Neg` unary operator is no longer implemented for `UnitComplex` and `UnitQuaternion`. This caused
hard-to-track errors when we mistakenly write, e.g., `-q * v` instead of `-(q * v)`.
* The `na::convert_unchecked` is no longer marked as unsafe.
## [0.20.0]
### Added
* `cholesky.rank_one_update(...)` which performs a rank-one update on the cholesky decomposition of a matrix.
* `From<&Matrix>` is now implemented for matrix slices.
* `.try_set_magnitude(...)` which sets the magnitude of a vector, while keeping its direction.
* Implementations of `From` and `Into` for the conversion between matrix slices and standard (`&[N]` `&mut [N]`) slices.
### Modified
* We started some major changes in order to allow non-Copy types to be used as scalar types inside of matrices/vectors.
## [0.19.0]
### Added
* `.remove_rows_at` and `remove_columns_at` which removes a set of rows or columns (specified by indices) from a matrix.
* Several formatting traits have been implemented for all matrices/vectors: `LowerExp`, `UpperExp`, `Octal`, `LowerHex`,
`UpperHex`, `Binary`, `Pointer`.
* `UnitQuaternion::quaternions_mean(...)` which computes the mean rotation of a set of unit quaternions. This implements
the algorithm from _Oshman, Yaakov, and Avishy Carmi, "Attitude estimation from vector observations using a genetic-algorithm-embedded quaternion particle filter."
the algorithm from _Oshman, Yaakov, and Avishy Carmi, "Attitude estimation from vector observations using a
genetic-algorithm-embedded quaternion particle filter."
### Modified
* It is now possible to get the `min/max` element of unsigned integer matrices.
### Added to nalgebra-glm
* Some infinite and reversed perspectives: `::infinite_perspective_rh_no`, `::infinite_perspective_rh_zo`,
`::reversed_perspective_rh_zo`, and `::reversed_infinite_perspective_rh_zo`.
## [0.18.0]
This release adds full complex number support to nalgebra. This includes all common vector/matrix operations as well
as matrix decomposition. This excludes geometric type (like `Isometry`, `Rotation`, `Translation`, etc.) from the
`geometry` module.
### Added
#### Quaternion and geometric operations
* Add trigonometric functions for quaternions: `.cos, .sin, .tan, .acos, .asin, .atan, .cosh, .sinh, .tanh, .acosh, .asinh, .atanh`.
* Add trigonometric functions for
quaternions: `.cos, .sin, .tan, .acos, .asin, .atan, .cosh, .sinh, .tanh, .acosh, .asinh, .atanh`.
* Add geometric algebra operations for quaternions: `.inner, .outer, .project, .rejection`
* Add `.left_div, .right_div` for quaternions.
* Add `.renormalize` to `Unit<...>` and `Rotation3` to correct potential drift due to repeated operations.
Those drifts could cause them not to be pure rotations anymore.
#### Convolution
* `.convolve_full(kernel)` returns the convolution of `self` by `kernel`.
* `.convolve_valid(kernel)` returns the convolution of `self` by `kernel` after removal of all the elements relying on zero-padding.
* `.convolve_valid(kernel)` returns the convolution of `self` by `kernel` after removal of all the elements relying on
zero-padding.
* `.convolve_same(kernel)` returns the convolution of `self` by `kernel` with a result of the same size as `self`.
#### Complex number support
* Add the `::from_matrix` constructor too all rotation types to extract a rotation from a raw matrix.
* Add the `::from_matrix_eps` constructor too all rotation types to extract a rotation from a raw matrix. This takes
more argument than `::from_matrix` to control the convergence of the underlying optimization algorithm.
* Add `.camax()` which returns the matrix component with the greatest L1-norm.
* Add `.camin()` which returns the matrix component with the smallest L1-norm.
* Add `.ad_mul(b)` for matrix-multiplication of `self.adjoint() * b`.
* Add `.ad_mul_to(b)` which is the same as `.ad_mul` but with a provided matrix to be filled with the result of the multiplication.
* Add `.ad_mul_to(b)` which is the same as `.ad_mul` but with a provided matrix to be filled with the result of the
multiplication.
* Add BLAS operations involving complex conjugation (following similar names as the original BLAS spec):
* `.dotc(rhs)` equal to `self.adjoint() * rhs`.
* `.gerc(alpha, x, y, beta)` equivalent to `self = alpha * x * y.adjoint() + beta * self`
* `.hegerc` which is like `gerc` but for Hermitian matrices.
* `.syger` which is the new name of `.ger_symm` which is equivalent to `self = alpha * x * y.transpose() + beta * self`.
* `.sygemv` which is the new name of `.gemv_symm` which is equivalent to `self = alpha * a * x + beta * self` with `a` symmetric.
* `.syger` which is the new name of `.ger_symm` which is equivalent
to `self = alpha * x * y.transpose() + beta * self`.
* `.sygemv` which is the new name of `.gemv_symm` which is equivalent to `self = alpha * a * x + beta * self`
with `a` symmetric.
* `.hegemv(alpha, a, x, beta)` which is like `.sygemv` but with `a` Hermitian.
* `.gemv_ad(alpha, a, x, beta)` which is equivalent to `self = alpha * a.adjoint() * x + beta * self`.
* `.gemm_ad(alpha, a, b, beta)` which is equivalent to `self = alpha * a.adjoint() * b + beta * self`.
@ -369,14 +595,17 @@ as matrix decomposition. This excludes geometric type (like `Isometry`, `Rotatio
Note that all the other BLAS operation will continue to work for all fields, including floats and complex numbers.
### Renamed
* `RealSchur` has been renamed `Schur` because it can now work with complex matrices.
* `RealSchur` has been renamed `Schur` because it can now work with complex matrices.
## [0.17.0]
### Added
* Add swizzling up to dimension 3 for vectors. For example, you can do `v.zxy()` as an equivalent to `Vector3::new(v.z, v.x, v.y)`.
* Add swizzling up to dimension 3 for points. For example, you can do `p.zxy()` as an equivalent to `Point3::new(p.z, p.x, p.y)`.
* Add swizzling up to dimension 3 for vectors. For example, you can do `v.zxy()` as an equivalent
to `Vector3::new(v.z, v.x, v.y)`.
* Add swizzling up to dimension 3 for points. For example, you can do `p.zxy()` as an equivalent
to `Point3::new(p.z, p.x, p.y)`.
* Add `.copy_from_slice` to copy matrix components from a slice in column-major order.
* Add `.dot` to quaternions.
* Add `.zip_zip_map` for iterating on three matrices simultaneously, and applying a closure to them.
@ -387,7 +616,8 @@ Note that all the other BLAS operation will continue to work for all fields, inc
* Add `From/Into` impls to allow the conversion of any transformation type to a matrix.
* Add `Into` impls to convert a matrix slice into an owned matrix.
* Add `Point*::from_slice` to create a point from a slice.
* Add `.map_with_location` to matrices to apply a map which passes the component indices to the user-defined closure alongside
* Add `.map_with_location` to matrices to apply a map which passes the component indices to the user-defined closure
alongside
the component itself.
* Add impl `From<Vector>` for `Point`.
* Add impl `From<Vector4>` for `Quaternion`.
@ -397,7 +627,8 @@ Note that all the other BLAS operation will continue to work for all fields, inc
* Add `.to_homogeneous` to square matrices (and with dimensions higher than 1x1). This will increase their number of row
and columns by 1. The new column and row are filled with 0, except for the diagonal element which is set to 1.
* Implement `Extend<Vec>` for matrices with a dynamic storage. The provided `Vec` is assumed to represent a column-major
matrix with the same number of rows as the one being extended. This will effectively append new columns on the right of
matrix with the same number of rows as the one being extended. This will effectively append new columns on the right
of
the matrix being extended.
* Implement `Extend<Vec>` for vectors with a dynamic storage. This will concatenate the vector with the given `Vec`.
* Implement `Extend<Matrix<...>>` for matrices with dynamic storage. This will concatenate the columns of both matrices.
@ -406,10 +637,12 @@ Note that all the other BLAS operation will continue to work for all fields, inc
* Add a `.len()` method to retrieve the size of a `MatrixVec`.
### Modified
* The orthographic projection no longer require that `bottom < top`, that `left < right`, and that `znear < zfar`. The
only restriction now ith that they must not be equal (in which case the projection would be singular).
* The `Point::from_coordinates` methods is deprecated. Use `Point::from` instead.
* The `.transform_point` and `.transform_vector` methods are now inherent methods for matrices so that the user does not have to
* The `.transform_point` and `.transform_vector` methods are now inherent methods for matrices so that the user does not
have to
explicitly import the `Transform` trait from the alga crate.
* Renamed the matrix storage types: `MatrixArray` -> `ArrayStorage` and `MatrixVec` -> `VecStorage`.
* Renamed `.unwrap()` to `.into_inner()` for geometric types that wrap another type.
@ -417,32 +650,46 @@ Note that all the other BLAS operation will continue to work for all fields, inc
* Deprecate several functions at the root of the crate (replaced by methods).
### Removed
* Remove the `Deref` impl for `MatrixVec` as it could cause hard-to-understand compilation errors.
### nalgebra-glm
* Add several alternative projection computations, e.g., `ortho_lh`, `ortho_lh_no`, `perspective_lh`, etc.
* Add features matching those of nalgebra, in particular: `serde-serialize`, `abmonation-serialize`, std` (enabled by default).
* Add features matching those of nalgebra, in particular:`serde-serialize`, `abmonation-serialize`, std` (enabled by
default).
## [0.16.0]
All dependencies have been updated to their latest versions.
## Modified
* Adjust `UnitQuaternion`s, `Rotation3`s, and `Rotation2`s generated from the `Standard` distribution to be uniformly distributed.
* Adjust `UnitQuaternion`s, `Rotation3`s, and `Rotation2`s generated from the `Standard` distribution to be uniformly
distributed.
### Added
* Add a feature `stdweb` to activate the dependency feature `rand/stdweb`.
* Add blas-like methods `.imin()` and `.imax()` that return the index of the minimum and maximum entry of a vector.
* Add construction of a `Point` from an array by implementing the `From` trait.
* Add support for generating uniformly distributed random unit column vectors using the `Standard` distribution.
## [0.15.0]
The most notable change of this release is the support for using part of the library without the rust standard
library (i.e. it supports `#![no_std]`). See the corresponding [documentation](https://nalgebra.org/wasm_and_embedded_programming/).
library (i.e. it supports `#![no_std]`). See the
corresponding [documentation](https://nalgebra.org/wasm_and_embedded_programming/).
### Modified
* Rename the `core` module to `base` to avoid conflicts with the `core` crate implicitly imported when
`#![no_std]` is enabled.
* Constructors of the `MatrixSlice*` types have been renamed from `new_*` to `from_slice_*`. This was
necessary to avoid the `incoherent_fundamental_impls` lint that is going to become a hard error.
### Added
* Add `UnitQuaternion` constructor `::new_eps(...)` and `::from_scaled_axis_eps(...)` that return the
identity if the magnitude of the input axisangle is smaller than the epsilon provided.
* Add methods `.rotation_between_axis(...)` and `.scaled_rotation_between_axis(...)` to `UnitComplex`
@ -452,9 +699,13 @@ library (i.e. it supports `#![no_std]`). See the corresponding [documentation](h
* Add functions to construct a random matrix with a user-defined distribution: `::from_distribution(...)`.
## [0.14.0]
### Modified
* Allow the `Isometry * Unit<Vector>` multiplication.
### Added
* Add blas-like operations: `.quadform(...)` and `.quadform_tr(...)` to compute respectively
the quadratic forms `self = alpha * A.transpose() * B * A + beta * self` and
`alpha * A * B * A.transpose() + beta * self`. Here, `A, B` are matrices with
@ -484,8 +735,6 @@ library (i.e. it supports `#![no_std]`). See the corresponding [documentation](h
`UnitQuaternion::rotation_between_axis(...)` that take Unit vectors instead of
Vector as arguments.
## [0.13.0]
The **nalgebra-lapack** crate has been updated. This now includes a broad range
@ -495,6 +744,7 @@ This adds support for serialization using the
[abomonation](https://crates.io/crates/abomonation) crate.
### Breaking semantic change
* The implementation of slicing with steps now matches the documentation.
Before, step identified the number to add to pass from one column/row index
to the next one. This made 0 step invalid. Now (and on the documentation so
@ -503,6 +753,7 @@ This adds support for serialization using the
example, a step of, say, 3 on previous versions should now bet set to 2.
### Modified
* The trait `Axpy` has been replaced by a method `.axpy`.
* The alias `MatrixNM` is now deprecated. Use `MatrixMN` instead (we
reordered M and N to be in alphabetical order).
@ -512,6 +763,7 @@ This adds support for serialization using the
`.component_div_assign(...)` instead.
### Added
* `alga::general::Real` is now re-exported by nalgebra.
elements.)
* `::zeros(...)` that creates a matrix filled with zeroes.
@ -547,17 +799,20 @@ Pure Rust implementation of some Blas operations:
* `.ger_symm(...)` is the same as `.ger` except that `self` is assumed symmetric.
New slicing methods:
* `.rows_range(...)` that retrieves a reference to a range of rows.
* `.rows_range_mut(...)` that retrieves a mutable reference to a range of rows.
* `.columns_range(...)` that retrieves a reference to a range of columns.
* `.columns_range_mut(...)` that retrieves a mutable reference to a range of columns.
Matrix decompositions implemented in pure Rust:
* Cholesky, SVD, LU, QR, Hessenberg, Schur, Symmetric eigendecompositions,
Bidiagonal, Symmetric tridiagonal
* Computation of householder reflectors and givens rotations.
Matrix edition:
* `.upper_triangle()` extracts the upper triangle of a matrix, including the diagonal.
* `.lower_triangle()` extracts the lower triangle of a matrix, including the diagonal.
* `.fill(...)` fills the matrix with a single value.
@ -574,37 +829,45 @@ Matrix edition:
* `.swap_columns(...)` swaps two columns.
Column removal:
* `.remove_column(...)` removes one column.
* `.remove_fixed_columns<D>(...)` removes `D` columns.
* `.remove_columns(...)` removes a number of columns known at run-time.
Row removal:
* `.remove_row(...)` removes one row.
* `.remove_fixed_rows<D>(...)` removes `D` rows.
* `.remove_rows(...)` removes a number of rows known at run-time.
Column insertion:
* `.insert_column(...)` adds one column at the given position.
* `.insert_fixed_columns<D>(...)` adds `D` columns at the given position.
* `.insert_columns(...)` adds at the given position a number of columns known at run-time.
Row insertion:
* `.insert_row(...)` adds one row at the given position.
* `.insert_fixed_rows<D>(...)` adds `D` rows at the given position.
* `.insert_rows(...)` adds at the given position a number of rows known at run-time.
## [0.12.0]
The main change of this release is the update of the dependency serde to 1.0.
### Added
* `.trace()` that computes the trace of a matrix (the sum of its diagonal
elements.)
## [0.11.0]
The [website](https://nalgebra.org) has been fully rewritten and gives a good
overview of all the added/modified features.
This version is a major rewrite of the library. Major changes are:
* Algebraic traits are now defined by the [alga](https://crates.io/crates/alga) crate.
All other mathematical traits, except `Axpy` have been removed from
**nalgebra**.
@ -622,9 +885,11 @@ This version is a major rewrite of the library. Major changes are:
* Matrix **slices** are now implemented.
### Added
Lots of features including rectangular matrices, slices, and Serde
serialization. Refer to the brand new [website](https://nalgebra.org) for more
details. The following free-functions have been added as well:
* `::id()` that returns the universal [identity element](https://nalgebra.org/performance_tricks/#the-id-type)
of type `Id`.
* `::inf_sup()` that returns both the infimum and supremum of a value at the
@ -634,6 +899,7 @@ details. The following free-functions have been added as well:
the interval width to it.
### Modified
* `::cast` -> `::convert`
* `point.as_vector()` -> `point.coords`
* `na::origin` -> `P::origin()`
@ -644,6 +910,7 @@ details. The following free-functions have been added as well:
* `::angle_between` -> `::angle`
Componentwise multiplication and division has been replaced by methods:
* multiplication -> `.componentwise_mul`, `.componentwise_mul_mut`.
* division -> `.componentwise_div`, `.componentwise_div_mut`.
@ -653,8 +920,8 @@ only:
`.eig`), `::hessenberg`, `::qr`, `::to_homogeneous`, `::to_rotation_matrix`,
`::transpose`, `::shape`.
The following free-functions are now replaced by static methods only:
* `::householder_matrix` under the name `::new_householder_generic`
* `::identity`
* `::new_identity` under the name `::identity`
@ -663,6 +930,7 @@ The following free-functions are now replaced by static methods only:
The following free-function are now replaced methods accessible through traits
only:
* `::transform` -> methods `.transform_point` and `.transform_vector` of the `alga::linear::Transformation` trait.
* `::inverse_transform` -> methods `.inverse_transform_point` and
`.inverse_transform_vector` of the `alga::linear::ProjectiveTransformation`
@ -679,9 +947,8 @@ only:
`alga::linear::Rotation` trait.
* `::is_zero` -> method with the same name from `num::Zero`.
### Removed
* The free functions `::prepend_rotation`, `::append_rotation`,
`::append_rotation_wrt_center`, `::append_rotation_wrt_point`,
`::append_transformation`, and `::append_translation ` have been removed.
@ -705,11 +972,14 @@ only:
`rotation.angle()` and `rotation.axis()`.
## [0.10.0]
### Added
Binary operations are now allowed between references as well. For example
`Vector3<f32> + &Vector3<f32>` is now possible.
### Modified
Removed unused parameters to methods from the `ApproxEq` trait. Those were
required before rust 1.0 to help type inference. They are not needed any more
since it now allowed to write for a type `T` that implements `ApproxEq`:
@ -717,7 +987,9 @@ since it now allowed to write for a type `T` that implements `ApproxEq`:
`ApproxEq::approx_epsilon(None::<T>)`.
## [0.9.0]
### Modified
* Renamed:
- `::from_col_vector` -> `::from_column_vector`
- `::from_col_iter` -> `::from_column_iter`
@ -739,11 +1011,13 @@ Other similar trait changes are to be expected in the future, e.g., for the
Methods marked `unsafe` for reasons unrelated to memory safety are no
longer unsafe. Instead, their name end with `_unchecked`. In particular:
* `Rotation3::new_with_matrix` -> `Rotation3::from_matrix_unchecked`
* `PerspectiveMatrix3::new_with_matrix` -> `PerspectiveMatrix3::from_matrix_unchecked`
* `OrthographicMatrix3::new_with_matrix` -> `OrthographicMatrix3::from_matrix_unchecked`
### Added
- A `Unit<T>` type that wraps normalized values. In particular,
`UnitQuaternion<N>` is now an alias for `Unit<Quaternion<N>>`.
- `.ln()`, `.exp()` and `.powf(..)` for quaternions and unit quaternions.
@ -760,7 +1034,9 @@ crate for vectors, rotations and points. To enable them, activate the
`abstract_algebra` feature.
## [0.8.0]
### Modified
* Almost everything (types, methods, and traits) now use fulls names instead
of abbreviations (e.g. `Vec3` becomes `Vector3`). Most changes are obvious.
Note however that:
@ -774,19 +1050,24 @@ crate for vectors, rotations and points. To enable them, activate the
e.g., `vec.rs` becomes `vector.rs`.
## [0.7.0]
### Added
* Added implementation of assignment operators (+=, -=, etc.) for
everything.
### Modified
* Points and vectors are now linked to each other with associated types
(on the PointAsVector trait).
## [0.6.0]
**Announcement:** a users forum has been created for `nalgebra`, `ncollide`, and `nphysics`. See
you [there](https://users.nphysics.org)!
### Added
* Added a dependency to [generic-array](https://crates.io/crates/generic-array). Feature-gated:
requires `features="generic_sizes"`.
* Added statically sized vectors with user-defined sizes: `VectorN`. Feature-gated: requires
@ -795,10 +1076,13 @@ you [there](https://users.nphysics.org)!
translation): `Similarity2`, `Similarity3`.
### Removed
* Removed zero-sized elements `Vector0`, `Point0`.
* Removed 4-dimensional transformations `Rotation4` and `Isometry4` (which had an implementation too incomplete to be useful).
* Removed 4-dimensional transformations `Rotation4` and `Isometry4` (which had an implementation too incomplete to be
useful).
### Modified
* Vectors are now multipliable with isometries. This will result into a pure rotation (this is how
vectors differ from point semantically: they design directions, so they are not translatable).
* `{Isometry3, Rotation3}::look_at` reimplemented and renamed to `::look_at_rh` and `::look_at_lh` to agree

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra"
version = "0.30.1"
version = "0.32.3"
authors = [ "Sébastien Crozet <developer@crozet.re>" ]
description = "General-purpose linear algebra library with transformations and statically-sized or dynamically-sized matrices."
@ -10,7 +10,7 @@ repository = "https://github.com/dimforge/nalgebra"
readme = "README.md"
categories = [ "science", "mathematics", "wasm", "no-std" ]
keywords = [ "linear", "algebra", "matrix", "vector", "math" ]
license = "BSD-3-Clause"
license = "Apache-2.0"
edition = "2018"
exclude = ["/ci/*", "/.travis.yml", "/Makefile"]
@ -23,7 +23,7 @@ path = "src/lib.rs"
[features]
default = [ "std", "macros" ]
std = [ "matrixmultiply", "simba/std" ]
std = [ "matrixmultiply", "num-traits/std", "num-complex/std", "num-rational/std", "approx/std", "simba/std" ]
sparse = [ ]
debug = [ "approx/num-complex", "rand" ]
alloc = [ ]
@ -32,12 +32,11 @@ compare = [ "matrixcompare-core" ]
libm = [ "simba/libm" ]
libm-force = [ "simba/libm_force" ]
macros = [ "nalgebra-macros" ]
cuda = [ "cust_core", "simba/cuda" ]
# Conversion
convert-mint = [ "mint" ]
convert-bytemuck = [ "bytemuck" ]
convert-glam013 = [ "glam013" ]
convert-glam014 = [ "glam014" ]
convert-glam015 = [ "glam015" ]
convert-glam016 = [ "glam016" ]
@ -45,6 +44,11 @@ convert-glam017 = [ "glam017" ]
convert-glam018 = [ "glam018" ]
convert-glam019 = [ "glam019" ]
convert-glam020 = [ "glam020" ]
convert-glam021 = [ "glam021" ]
convert-glam022 = [ "glam022" ]
convert-glam023 = [ "glam023" ]
convert-glam024 = [ "glam024" ]
convert-glam025 = [ "glam025" ]
# Serialization
## To use serde in a #[no-std] environment, enable the
@ -53,8 +57,8 @@ convert-glam020 = [ "glam020" ]
## `serde-serialize`.
serde-serialize-no-std = [ "serde", "num-complex/serde" ]
serde-serialize = [ "serde-serialize-no-std", "serde/std" ]
rkyv-serialize-no-std = [ "rkyv" ]
rkyv-serialize = [ "rkyv-serialize-no-std", "rkyv/std" ]
rkyv-serialize-no-std = [ "rkyv/size_32" ]
rkyv-serialize = [ "rkyv-serialize-no-std", "rkyv/std", "rkyv/validation" ]
# Randomness
## To use rand in a #[no-std] environment, enable the
@ -66,21 +70,22 @@ rand = [ "rand-no-std", "rand-package/std", "rand-package/std_rng", "rand
arbitrary = [ "quickcheck" ]
proptest-support = [ "proptest" ]
slow-tests = []
rkyv-safe-deser = [ "rkyv-serialize", "rkyv/validation" ]
[dependencies]
nalgebra-macros = { version = "0.1", path = "nalgebra-macros", optional = true }
nalgebra-macros = { version = "0.2.1", path = "nalgebra-macros", optional = true }
typenum = "1.12"
rand-package = { package = "rand", version = "0.8", optional = true, default-features = false }
num-traits = { version = "0.2", default-features = false }
num-complex = { version = "0.4", default-features = false }
num-rational = { version = "0.4", default-features = false }
approx = { version = "0.5", default-features = false }
simba = { version = "0.7", default-features = false }
simba = { version = "0.8", default-features = false }
alga = { version = "0.9", default-features = false, optional = true }
rand_distr = { version = "0.4", default-features = false, optional = true }
matrixmultiply = { version = "0.3", optional = true }
serde = { version = "1.0", default-features = false, features = [ "derive" ], optional = true }
rkyv = { version = "~0.6.4", default-features = false, features = ["const_generics"], optional = true }
rkyv = { version = "0.7.41", default-features = false, optional = true }
mint = { version = "0.5", optional = true }
quickcheck = { version = "1", optional = true }
pest = { version = "2", optional = true }
@ -88,7 +93,6 @@ pest_derive = { version = "2", optional = true }
bytemuck = { version = "1.5", optional = true }
matrixcompare-core = { version = "0.1", optional = true }
proptest = { version = "1", optional = true, default-features = false, features = ["std"] }
glam013 = { package = "glam", version = "0.13", optional = true }
glam014 = { package = "glam", version = "0.14", optional = true }
glam015 = { package = "glam", version = "0.15", optional = true }
glam016 = { package = "glam", version = "0.16", optional = true }
@ -96,14 +100,19 @@ glam017 = { package = "glam", version = "0.17", optional = true }
glam018 = { package = "glam", version = "0.18", optional = true }
glam019 = { package = "glam", version = "0.19", optional = true }
glam020 = { package = "glam", version = "0.20", optional = true }
cust_core = { version = "0.1", optional = true }
glam021 = { package = "glam", version = "0.21", optional = true }
glam022 = { package = "glam", version = "0.22", optional = true }
glam023 = { package = "glam", version = "0.23", optional = true }
glam024 = { package = "glam", version = "0.24", optional = true }
glam025 = { package = "glam", version = "0.25", optional = true }
rayon = { version = "1.6", optional = true }
[dev-dependencies]
serde_json = "1.0"
rand_xorshift = "0.3"
rand_isaac = "0.3"
criterion = { version = "0.3", features = ["html_reports"] }
criterion = { version = "0.4", features = ["html_reports"] }
nalgebra = { path = ".", features = ["debug", "compare", "rand", "macros"]}
# For matrix comparison macro
matrixcompare = "0.3.0"
@ -131,6 +140,7 @@ required-features = ["rand"]
lto = true
[package.metadata.docs.rs]
# Enable certain features when building docs for docs.rs
features = [ "proptest-support", "compare", "macros", "rand" ]
# Enable all the features when building the docs on docs.rs
all-features = true
# define the configuration attribute `docsrs`
rustdoc-args = ["--cfg", "docsrs"]

View File

@ -29,19 +29,3 @@
</p>
-----
## Acknowledgements
nalgebra is supported by our **platinum** sponsors:
<p>
<a href="https://embark-studios.com">
<img src="https://www.embark.dev/img/logo_black.png" width="301px">
</a>
</p>
And our gold sponsors:
<p>
<a href="https://fragcolor.com">
<img src="https://dimforge.com/img/fragcolor_logo1_color_black.svg" width="151px">
</a>
</p>

View File

@ -53,7 +53,7 @@ fn mat_div_scalar(b: &mut criterion::Criterion) {
b.bench_function("mat_div_scalar", move |bh| {
bh.iter(|| {
let mut aa = a.clone();
let mut b = aa.slice_mut((0, 0), (1000, 1000));
let mut b = aa.view_mut((0, 0), (1000, 1000));
b /= n
})
});
@ -142,7 +142,7 @@ fn iter(bench: &mut criterion::Criterion) {
bench.bench_function("iter", move |bh| {
bh.iter(|| {
for value in a.iter() {
criterion::black_box(value);
std::hint::black_box(value);
}
})
});
@ -154,7 +154,7 @@ fn iter_rev(bench: &mut criterion::Criterion) {
bench.bench_function("iter_rev", move |bh| {
bh.iter(|| {
for value in a.iter().rev() {
criterion::black_box(value);
std::hint::black_box(value);
}
})
});

View File

@ -1,4 +1,3 @@
#![feature(bench_black_box)]
#![allow(unused_macros)]
extern crate nalgebra as na;

View File

@ -4,7 +4,7 @@ version = "0.0.0"
authors = [ "You" ]
[dependencies]
nalgebra = "0.30.0"
nalgebra = "0.32.0"
[[bin]]
name = "example"

View File

@ -28,7 +28,7 @@ where
}
/// Reflects a 3D vector wrt. the 3D plane with normal `plane_normal`.
/// /!\ This is an exact replicate of `reflect_wrt_hyperplane2, but for 3D.
/// /!\ This is an exact replicate of `reflect_wrt_hyperplane2`, but for 3D.
fn reflect_wrt_hyperplane3<T>(plane_normal: &Unit<Vector3<T>>, vector: &Vector3<T>) -> Vector3<T>
where
T: RealField,

View File

@ -2,7 +2,7 @@
extern crate nalgebra as na;
use na::{DMatrix, Dynamic, Matrix2x3, Matrix3x2, Const};
use na::{DMatrix, Dyn, Matrix2x3, Matrix3x2, Const};
fn main() {
// Matrices can be reshaped in-place without moving or copying values.
@ -46,9 +46,9 @@ fn main() {
],
);
let dm3 = dm1.reshape_generic(Dynamic::new(6), Dynamic::new(2));
let dm3 = dm1.reshape_generic(Dyn(6), Dyn(2));
assert_eq!(dm3, dm2);
// Invalid reshapings of dynamic matrices will panic at run-time.
//let dm4 = dm3.reshape_generic(Dynamic::new(6), Dynamic::new(6));
//let dm4 = dm3.reshape_generic(Dyn(6), Dyn(6));
}

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra-glm"
version = "0.16.0"
version = "0.18.0"
authors = ["sebcrozet <developer@crozet.re>"]
description = "A computer-graphics oriented API for nalgebra, inspired by the C++ GLM library."
@ -10,7 +10,7 @@ repository = "https://github.com/dimforge/nalgebra"
readme = "../README.md"
categories = [ "science", "mathematics", "wasm", "no standard library" ]
keywords = [ "linear", "algebra", "matrix", "vector", "math" ]
license = "BSD-3-Clause"
license = "Apache-2.0"
edition = "2018"
[badges]
@ -21,12 +21,10 @@ default = [ "std" ]
std = [ "nalgebra/std", "simba/std" ]
arbitrary = [ "nalgebra/arbitrary" ]
serde-serialize = [ "nalgebra/serde-serialize-no-std" ]
cuda = [ "nalgebra/cuda" ]
# Conversion
convert-mint = [ "nalgebra/mint" ]
convert-bytemuck = [ "nalgebra/bytemuck" ]
convert-glam013 = [ "nalgebra/glam013" ]
convert-glam014 = [ "nalgebra/glam014" ]
convert-glam015 = [ "nalgebra/glam015" ]
convert-glam016 = [ "nalgebra/glam016" ]
@ -36,5 +34,5 @@ convert-glam018 = [ "nalgebra/glam018" ]
[dependencies]
num-traits = { version = "0.2", default-features = false }
approx = { version = "0.5", default-features = false }
simba = { version = "0.7", default-features = false }
nalgebra = { path = "..", version = "0.30", default-features = false }
simba = { version = "0.8", default-features = false }
nalgebra = { path = "..", version = "0.32", default-features = false }

1
nalgebra-glm/LICENSE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE

View File

@ -5,38 +5,38 @@ use na::{
/// A matrix with components of type `T`. It has `R` rows, and `C` columns.
///
/// In this library, vectors, represented as [`TVec`](type.TVec.html) and
/// In this library, vectors, represented as [`TVec`] and
/// friends, are also matrices. Operations that operate on a matrix will
/// also work on a vector.
///
/// # See also:
///
/// * [`TMat2`](type.TMat2.html)
/// * [`TMat2x2`](type.TMat2x2.html)
/// * [`TMat2x3`](type.TMat2x3.html)
/// * [`TMat2x4`](type.TMat2x4.html)
/// * [`TMat3`](type.TMat3.html)
/// * [`TMat3x2`](type.TMat3x2.html)
/// * [`TMat3x3`](type.TMat3x3.html)
/// * [`TMat3x4`](type.TMat3x4.html)
/// * [`TMat4`](type.TMat4.html)
/// * [`TMat4x2`](type.TMat4x2.html)
/// * [`TMat4x3`](type.TMat4x3.html)
/// * [`TMat4x4`](type.TMat4x4.html)
/// * [`TVec`](type.TVec.html)
/// * [`TMat2`]
/// * [`TMat2x2`]
/// * [`TMat2x3`]
/// * [`TMat2x4`]
/// * [`TMat3`]
/// * [`TMat3x2`]
/// * [`TMat3x3`]
/// * [`TMat3x4`]
/// * [`TMat4`]
/// * [`TMat4x2`]
/// * [`TMat4x3`]
/// * [`TMat4x4`]
/// * [`TVec`]
pub type TMat<T, const R: usize, const C: usize> = SMatrix<T, R, C>;
/// A column vector with components of type `T`. It has `D` rows (and one column).
///
/// In this library, vectors are represented as a single column matrix, so
/// operations on [`TMat`](type.TMat.html) are also valid on vectors.
/// operations on [`TMat`] are also valid on vectors.
///
/// # See also:
///
/// * [`TMat`](type.TMat.html)
/// * [`TVec1`](type.TVec1.html)
/// * [`TVec2`](type.TVec2.html)
/// * [`TVec3`](type.TVec3.html)
/// * [`TVec4`](type.TVec4.html)
/// * [`TMat`]
/// * [`TVec1`]
/// * [`TVec2`]
/// * [`TVec3`]
/// * [`TVec4`]
pub type TVec<T, const R: usize> = SVector<T, R>;
/// A quaternion with components of type `T`.
pub type Qua<T> = Quaternion<T>;
@ -47,28 +47,28 @@ pub type Qua<T> = Quaternion<T>;
///
/// ## Constructors:
///
/// * [`make_vec1`](fn.make_vec1.html)
/// * [`vec1`](fn.vec1.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec4_to_vec1`](fn.vec4_to_vec1.html)
/// * [`make_vec1()`](crate::make_vec1)
/// * [`vec1()`](crate::vec1)
/// * [`vec2_to_vec1()`](crate::vec2_to_vec1)
/// * [`vec3_to_vec1()`](crate::vec3_to_vec1)
/// * [`vec4_to_vec1()`](crate::vec4_to_vec1)
///
/// ## Related types:
///
/// * [`BVec1`](type.BVec1.html)
/// * [`DVec1`](type.DVec1.html)
/// * [`IVec1`](type.IVec1.html)
/// * [`I16Vec1`](type.I16Vec1.html)
/// * [`I32Vec1`](type.I32Vec1.html)
/// * [`I64Vec1`](type.I64Vec1.html)
/// * [`I8Vec1`](type.I8Vec1.html)
/// * [`TVec`](type.TVec.html)
/// * [`UVec1`](type.UVec1.html)
/// * [`U16Vec1`](type.U16Vec1.html)
/// * [`U32Vec1`](type.U32Vec1.html)
/// * [`U64Vec1`](type.U64Vec1.html)
/// * [`U8Vec1`](type.U8Vec1.html)
/// * [`Vec1`](type.Vec1.html)
/// * [`BVec1`]
/// * [`DVec1`]
/// * [`IVec1`]
/// * [`I16Vec1`]
/// * [`I32Vec1`]
/// * [`I64Vec1`]
/// * [`I8Vec1`]
/// * [`TVec`]
/// * [`UVec1`]
/// * [`U16Vec1`]
/// * [`U32Vec1`]
/// * [`U64Vec1`]
/// * [`U8Vec1`]
/// * [`Vec1`]
pub type TVec1<T> = TVec<T, 1>;
/// A 2D vector with components of type `T`.
///
@ -76,29 +76,28 @@ pub type TVec1<T> = TVec<T, 1>;
///
/// ## Constructors:
///
/// * [`make_vec2`](fn.make_vec2.html)
/// * [`vec2`](fn.vec2.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec4_to_vec2`](fn.vec4_to_vec2.html)
/// * [`make_vec2()`](crate::make_vec2)
/// * [`vec2()`](crate::vec2)
/// * [`vec1_to_vec2()`](crate::vec1_to_vec2)
/// * [`vec3_to_vec2()`](crate::vec3_to_vec2)
/// * [`vec4_to_vec2()`](crate::vec4_to_vec2)
///
/// ## Related types:
///
/// * [`vec2`](fn.vec2.html)
/// * [`BVec2`](type.BVec2.html)
/// * [`DVec2`](type.DVec2.html)
/// * [`IVec2`](type.IVec2.html)
/// * [`I16Vec2`](type.I16Vec2.html)
/// * [`I32Vec2`](type.I32Vec2.html)
/// * [`I64Vec2`](type.I64Vec2.html)
/// * [`I8Vec2`](type.I8Vec2.html)
/// * [`TVec`](type.TVec.html)
/// * [`UVec2`](type.UVec2.html)
/// * [`U16Vec2`](type.U16Vec2.html)
/// * [`U32Vec2`](type.U32Vec2.html)
/// * [`U64Vec2`](type.U64Vec2.html)
/// * [`U8Vec2`](type.U8Vec2.html)
/// * [`Vec2`](type.Vec2.html)
/// * [`BVec2`]
/// * [`DVec2`]
/// * [`IVec2`]
/// * [`I16Vec2`]
/// * [`I32Vec2`]
/// * [`I64Vec2`]
/// * [`I8Vec2`]
/// * [`TVec`]
/// * [`UVec2`]
/// * [`U16Vec2`]
/// * [`U32Vec2`]
/// * [`U64Vec2`]
/// * [`U8Vec2`]
/// * [`Vec2`]
pub type TVec2<T> = TVec<T, 2>;
/// A 3D vector with components of type `T`.
///
@ -106,29 +105,28 @@ pub type TVec2<T> = TVec<T, 2>;
///
/// ## Constructors:
///
/// * [`make_vec3`](fn.make_vec3.html)
/// * [`vec3`](fn.vec3.html)
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec4_to_vec3`](fn.vec4_to_vec3.html)
/// * [`make_vec3()`](crate::make_vec3)
/// * [`vec3()`](crate::vec3)
/// * [`vec1_to_vec3()`](crate::vec1_to_vec3)
/// * [`vec2_to_vec3()`](crate::vec2_to_vec3)
/// * [`vec4_to_vec3()`](crate::vec4_to_vec3)
///
/// ## Related types:
///
/// * [`vec3`](fn.vec3.html)
/// * [`BVec3`](type.BVec3.html)
/// * [`DVec3`](type.DVec3.html)
/// * [`IVec3`](type.IVec3.html)
/// * [`I16Vec3`](type.I16Vec3.html)
/// * [`I32Vec3`](type.I32Vec3.html)
/// * [`I64Vec3`](type.I64Vec3.html)
/// * [`I8Vec3`](type.I8Vec3.html)
/// * [`TVec`](type.TVec.html)
/// * [`UVec3`](type.UVec3.html)
/// * [`U16Vec3`](type.U16Vec3.html)
/// * [`U32Vec3`](type.U32Vec3.html)
/// * [`U64Vec3`](type.U64Vec3.html)
/// * [`U8Vec3`](type.U8Vec3.html)
/// * [`Vec3`](type.Vec3.html)
/// * [`BVec3`]
/// * [`DVec3`]
/// * [`IVec3`]
/// * [`I16Vec3`]
/// * [`I32Vec3`]
/// * [`I64Vec3`]
/// * [`I8Vec3`]
/// * [`TVec`]
/// * [`UVec3`]
/// * [`U16Vec3`]
/// * [`U32Vec3`]
/// * [`U64Vec3`]
/// * [`U8Vec3`]
/// * [`Vec3`]
pub type TVec3<T> = TVec<T, 3>;
/// A 4D vector with components of type `T`.
///
@ -136,28 +134,27 @@ pub type TVec3<T> = TVec<T, 3>;
///
/// ## Constructors:
///
/// * [`make_vec4`](fn.make_vec4.html)
/// * [`vec4`](fn.vec4.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`make_vec4()`](crate::make_vec4)
/// * [`vec4()`](crate::vec4)
/// * [`vec1_to_vec4()`](crate::vec1_to_vec4)
/// * [`vec2_to_vec4()`](crate::vec2_to_vec4)
/// * [`vec3_to_vec4()`](crate::vec3_to_vec4)
///
/// ## Related types:
///
/// * [`vec4`](fn.vec4.html)
/// * [`BVec4`](type.BVec4.html)
/// * [`DVec4`](type.DVec4.html)
/// * [`IVec4`](type.IVec4.html)
/// * [`I16Vec4`](type.I16Vec4.html)
/// * [`I32Vec4`](type.I32Vec4.html)
/// * [`I64Vec4`](type.I64Vec4.html)
/// * [`I8Vec4`](type.I8Vec4.html)
/// * [`UVec4`](type.UVec4.html)
/// * [`U16Vec4`](type.U16Vec4.html)
/// * [`U32Vec4`](type.U32Vec4.html)
/// * [`U64Vec4`](type.U64Vec4.html)
/// * [`U8Vec4`](type.U8Vec4.html)
/// * [`Vec4`](type.Vec4.html)
/// * [`BVec4`]
/// * [`DVec4`]
/// * [`IVec4`]
/// * [`I16Vec4`]
/// * [`I32Vec4`]
/// * [`I64Vec4`]
/// * [`I8Vec4`]
/// * [`UVec4`]
/// * [`U16Vec4`]
/// * [`U32Vec4`]
/// * [`U64Vec4`]
/// * [`U8Vec4`]
/// * [`Vec4`]
pub type TVec4<T> = TVec<T, 4>;
/// A 1D vector with boolean components.
pub type BVec1 = TVec1<bool>;

View File

@ -1,5 +1,4 @@
use core::mem;
use na;
use crate::aliases::{TMat, TVec};
use crate::traits::Number;
@ -20,7 +19,7 @@ use crate::RealNumber;
///
/// # See also:
///
/// * [`sign`](fn.sign.html)
/// * [`sign()`]
pub fn abs<T: Number, const R: usize, const C: usize>(x: &TMat<T, R, C>) -> TMat<T, R, C> {
x.abs()
}
@ -37,11 +36,11 @@ pub fn abs<T: Number, const R: usize, const C: usize>(x: &TMat<T, R, C>) -> TMat
///
/// # See also:
///
/// * [`ceil`](fn.ceil.html)
/// * [`floor`](fn.floor.html)
/// * [`fract`](fn.fract.html)
/// * [`round`](fn.round.html)
/// * [`trunc`](fn.trunc.html)
/// * [`ceil()`]
/// * [`floor()`]
/// * [`fract()`]
/// * [`round()`]
/// * [`trunc()`]
pub fn ceil<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| x.ceil())
}
@ -65,8 +64,8 @@ pub fn ceil<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`clamp`](fn.clamp.html)
/// * [`clamp_vec`](fn.clamp_vec.html)
/// * [`clamp()`]
/// * [`clamp_vec()`]
pub fn clamp_scalar<T: Number>(x: T, min_val: T, max_val: T) -> T {
na::clamp(x, min_val, max_val)
}
@ -89,8 +88,8 @@ pub fn clamp_scalar<T: Number>(x: T, min_val: T, max_val: T) -> T {
///
/// # See also:
///
/// * [`clamp_scalar`](fn.clamp_scalar.html)
/// * [`clamp_vec`](fn.clamp_vec.html)
/// * [`clamp_scalar()`]
/// * [`clamp_vec()`]
pub fn clamp<T: Number, const D: usize>(x: &TVec<T, D>, min_val: T, max_val: T) -> TVec<T, D> {
x.map(|x| na::clamp(x, min_val, max_val))
}
@ -120,8 +119,8 @@ pub fn clamp<T: Number, const D: usize>(x: &TVec<T, D>, min_val: T, max_val: T)
///
/// # See also:
///
/// * [`clamp_scalar`](fn.clamp_scalar.html)
/// * [`clamp`](fn.clamp.html)
/// * [`clamp_scalar()`]
/// * [`clamp()`]
pub fn clamp_vec<T: Number, const D: usize>(
x: &TVec<T, D>,
min_val: &TVec<T, D>,
@ -136,13 +135,13 @@ pub fn clamp_vec<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn float_bits_to_int(v: f32) -> i32 {
unsafe { mem::transmute(v) }
}
@ -153,13 +152,13 @@ pub fn float_bits_to_int(v: f32) -> i32 {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn float_bits_to_int_vec<const D: usize>(v: &TVec<f32, D>) -> TVec<i32, D> {
v.map(float_bits_to_int)
}
@ -170,13 +169,13 @@ pub fn float_bits_to_int_vec<const D: usize>(v: &TVec<f32, D>) -> TVec<i32, D> {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn float_bits_to_uint(v: f32) -> u32 {
unsafe { mem::transmute(v) }
}
@ -187,13 +186,13 @@ pub fn float_bits_to_uint(v: f32) -> u32 {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn float_bits_to_uint_vec<const D: usize>(v: &TVec<f32, D>) -> TVec<u32, D> {
v.map(float_bits_to_uint)
}
@ -210,10 +209,10 @@ pub fn float_bits_to_uint_vec<const D: usize>(v: &TVec<f32, D>) -> TVec<u32, D>
///
/// # See also:
///
/// * [`ceil`](fn.ceil.html)
/// * [`fract`](fn.fract.html)
/// * [`round`](fn.round.html)
/// * [`trunc`](fn.trunc.html)
/// * [`ceil()`]
/// * [`fract()`]
/// * [`round()`]
/// * [`trunc()`]
pub fn floor<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| x.floor())
}
@ -236,10 +235,10 @@ pub fn floor<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`ceil`](fn.ceil.html)
/// * [`floor`](fn.floor.html)
/// * [`round`](fn.round.html)
/// * [`trunc`](fn.trunc.html)
/// * [`ceil()`]
/// * [`floor()`]
/// * [`round()`]
/// * [`trunc()`]
pub fn fract<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| x.fract())
}
@ -258,13 +257,13 @@ pub fn fract<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn int_bits_to_float(v: i32) -> f32 {
f32::from_bits(v as u32)
}
@ -275,13 +274,13 @@ pub fn int_bits_to_float(v: i32) -> f32 {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`uint_bits_to_float()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn int_bits_to_float_vec<const D: usize>(v: &TVec<i32, D>) -> TVec<f32, D> {
v.map(int_bits_to_float)
}
@ -315,8 +314,8 @@ pub fn int_bits_to_float_vec<const D: usize>(v: &TVec<i32, D>) -> TVec<f32, D> {
///
/// # See also:
///
/// * [`mix`](fn.mix.html)
/// * [`mix_vec`](fn.mix_vec.html)
/// * [`mix()`]
/// * [`mix_vec()`]
pub fn mix_scalar<T: Number>(x: T, y: T, a: T) -> T {
x * (T::one() - a) + y * a
}
@ -336,8 +335,8 @@ pub fn mix_scalar<T: Number>(x: T, y: T, a: T) -> T {
///
/// # See also:
///
/// * [`mix_scalar`](fn.mix_scalar.html)
/// * [`mix_vec`](fn.mix_vec.html)
/// * [`mix_scalar()`]
/// * [`mix_vec()`]
pub fn mix<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, a: T) -> TVec<T, D> {
x * (T::one() - a) + y * a
}
@ -359,14 +358,14 @@ pub fn mix<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, a: T) -> T
///
/// # See also:
///
/// * [`mix_scalar`](fn.mix_scalar.html)
/// * [`mix`](fn.mix.html)
/// * [`mix_scalar()`]
/// * [`mix()`]
pub fn mix_vec<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
a: &TVec<T, D>,
) -> TVec<T, D> {
x.component_mul(&(TVec::<T, D>::repeat(T::one()) - a)) + y.component_mul(&a)
x.component_mul(&(TVec::<T, D>::repeat(T::one()) - a)) + y.component_mul(a)
}
/// Returns `x * (1.0 - a) + y * a`, i.e., the linear blend of the scalars x and y using the scalar value a.
@ -383,8 +382,8 @@ pub fn mix_vec<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`lerp`](fn.lerp.html)
/// * [`lerp_vec`](fn.lerp_vec.html)
/// * [`lerp()`]
/// * [`lerp_vec()`]
pub fn lerp_scalar<T: Number>(x: T, y: T, a: T) -> T {
mix_scalar(x, y, a)
}
@ -405,8 +404,8 @@ pub fn lerp_scalar<T: Number>(x: T, y: T, a: T) -> T {
///
/// # See also:
///
/// * [`lerp_scalar`](fn.lerp_scalar.html)
/// * [`lerp_vec`](fn.lerp_vec.html)
/// * [`lerp_scalar()`]
/// * [`lerp_vec()`]
pub fn lerp<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, a: T) -> TVec<T, D> {
mix(x, y, a)
}
@ -429,8 +428,8 @@ pub fn lerp<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, a: T) ->
///
/// # See also:
///
/// * [`lerp_scalar`](fn.lerp_scalar.html)
/// * [`lerp`](fn.lerp.html)
/// * [`lerp_scalar()`]
/// * [`lerp()`]
pub fn lerp_vec<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
@ -445,7 +444,7 @@ pub fn lerp_vec<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`modf`](fn.modf.html)
/// * [`modf()`]
pub fn modf_vec<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<T, D> {
x.zip_map(y, |x, y| x % y)
}
@ -454,7 +453,7 @@ pub fn modf_vec<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TV
///
/// # See also:
///
/// * [`modf_vec`](fn.modf_vec.html)
/// * [`modf_vec()`]
pub fn modf<T: Number>(x: T, i: T) -> T {
x % i
}
@ -473,10 +472,10 @@ pub fn modf<T: Number>(x: T, i: T) -> T {
///
/// # See also:
///
/// * [`ceil`](fn.ceil.html)
/// * [`floor`](fn.floor.html)
/// * [`fract`](fn.fract.html)
/// * [`trunc`](fn.trunc.html)
/// * [`ceil()`]
/// * [`floor()`]
/// * [`fract()`]
/// * [`trunc()`]
pub fn round<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| x.round())
}
@ -497,7 +496,7 @@ pub fn round<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`abs`](fn.abs.html)
/// * [`abs()`]
///
pub fn sign<T: Number, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| if x.is_zero() { T::zero() } else { x.signum() })
@ -545,10 +544,10 @@ pub fn step_vec<T: Number, const D: usize>(edge: &TVec<T, D>, x: &TVec<T, D>) ->
///
/// # See also:
///
/// * [`ceil`](fn.ceil.html)
/// * [`floor`](fn.floor.html)
/// * [`fract`](fn.fract.html)
/// * [`round`](fn.round.html)
/// * [`ceil()`]
/// * [`floor()`]
/// * [`fract()`]
/// * [`round()`]
pub fn trunc<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
x.map(|x| x.trunc())
}
@ -559,13 +558,13 @@ pub fn trunc<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float`](fn.uint_bits_to_float.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float()`]
pub fn uint_bits_to_float_scalar(v: u32) -> f32 {
f32::from_bits(v)
}
@ -576,13 +575,13 @@ pub fn uint_bits_to_float_scalar(v: u32) -> f32 {
///
/// # See also:
///
/// * [`float_bits_to_int`](fn.float_bits_to_int.html)
/// * [`float_bits_to_int_vec`](fn.float_bits_to_int_vec.html)
/// * [`float_bits_to_uint`](fn.float_bits_to_uint.html)
/// * [`float_bits_to_uint_vec`](fn.float_bits_to_uint_vec.html)
/// * [`int_bits_to_float`](fn.int_bits_to_float.html)
/// * [`int_bits_to_float_vec`](fn.int_bits_to_float_vec.html)
/// * [`uint_bits_to_float_scalar`](fn.uint_bits_to_float_scalar.html)
/// * [`float_bits_to_int()`]
/// * [`float_bits_to_int_vec()`]
/// * [`float_bits_to_uint()`]
/// * [`float_bits_to_uint_vec()`]
/// * [`int_bits_to_float()`]
/// * [`int_bits_to_float_vec()`]
/// * [`uint_bits_to_float_scalar()`]
pub fn uint_bits_to_float<const D: usize>(v: &TVec<u32, D>) -> TVec<f32, D> {
v.map(uint_bits_to_float_scalar)
}

View File

@ -91,6 +91,7 @@ pub fn mat2x4<T: Scalar>(m11: T, m12: T, m13: T, m14: T,
/// );
/// ```
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat3<T: Scalar>(m11: T, m12: T, m13: T,
m21: T, m22: T, m23: T,
m31: T, m32: T, m33: T) -> TMat3<T> {
@ -115,6 +116,7 @@ pub fn mat3x2<T: Scalar>(m11: T, m12: T,
/// Create a new 3x3 matrix.
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat3x3<T: Scalar>(m11: T, m12: T, m13: T,
m21: T, m22: T, m23: T,
m31: T, m32: T, m33: T) -> TMat3<T> {
@ -127,6 +129,7 @@ pub fn mat3x3<T: Scalar>(m11: T, m12: T, m13: T,
/// Create a new 3x4 matrix.
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat3x4<T: Scalar>(m11: T, m12: T, m13: T, m14: T,
m21: T, m22: T, m23: T, m24: T,
m31: T, m32: T, m33: T, m34: T) -> TMat3x4<T> {
@ -153,6 +156,7 @@ pub fn mat4x2<T: Scalar>(m11: T, m12: T,
/// Create a new 4x3 matrix.
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat4x3<T: Scalar>(m11: T, m12: T, m13: T,
m21: T, m22: T, m23: T,
m31: T, m32: T, m33: T,
@ -167,6 +171,7 @@ pub fn mat4x3<T: Scalar>(m11: T, m12: T, m13: T,
/// Create a new 4x4 matrix.
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat4x4<T: Scalar>(m11: T, m12: T, m13: T, m14: T,
m21: T, m22: T, m23: T, m24: T,
m31: T, m32: T, m33: T, m34: T,
@ -181,6 +186,7 @@ pub fn mat4x4<T: Scalar>(m11: T, m12: T, m13: T, m14: T,
/// Create a new 4x4 matrix.
#[rustfmt::skip]
#[allow(clippy::too_many_arguments)]
pub fn mat4<T: Scalar>(m11: T, m12: T, m13: T, m14: T,
m21: T, m22: T, m23: T, m24: T,
m31: T, m32: T, m33: T, m34: T,

View File

@ -5,7 +5,7 @@ use crate::RealNumber;
///
/// # See also:
///
/// * [`exp2`](fn.exp2.html)
/// * [`exp2()`]
pub fn exp<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| x.exp())
}
@ -14,7 +14,7 @@ pub fn exp<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`exp`](fn.exp.html)
/// * [`exp()`]
pub fn exp2<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| x.exp2())
}
@ -23,7 +23,7 @@ pub fn exp2<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`sqrt`](fn.sqrt.html)
/// * [`sqrt()`]
pub fn inversesqrt<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| T::one() / x.sqrt())
}
@ -32,7 +32,7 @@ pub fn inversesqrt<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D>
///
/// # See also:
///
/// * [`log2`](fn.log2.html)
/// * [`log2()`]
pub fn log<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| x.ln())
}
@ -41,7 +41,7 @@ pub fn log<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
///
/// # See also:
///
/// * [`log`](fn.log.html)
/// * [`log()`]
pub fn log2<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| x.log2())
}
@ -55,10 +55,10 @@ pub fn pow<T: RealNumber, const D: usize>(base: &TVec<T, D>, exponent: &TVec<T,
///
/// # See also:
///
/// * [`exp`](fn.exp.html)
/// * [`exp2`](fn.exp2.html)
/// * [`inversesqrt`](fn.inversesqrt.html)
/// * [`pow`](fn.pow.html)
/// * [`exp()`]
/// * [`exp2()`]
/// * [`inversesqrt()`]
/// * [`pow`]
pub fn sqrt<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> TVec<T, D> {
v.map(|x| x.sqrt())
}

View File

@ -1,5 +1,3 @@
use na;
use crate::aliases::{TMat4, TVec2, TVec3, TVec4};
use crate::RealNumber;
@ -41,11 +39,11 @@ pub fn pick_matrix<T: RealNumber>(
///
/// # See also:
///
/// * [`project_no`](fn.project_no.html)
/// * [`project_zo`](fn.project_zo.html)
/// * [`unproject`](fn.unproject.html)
/// * [`unproject_no`](fn.unproject_no.html)
/// * [`unproject_zo`](fn.unproject_zo.html)
/// * [`project_no()`]
/// * [`project_zo()`]
/// * [`unproject()`]
/// * [`unproject_no()`]
/// * [`unproject_zo()`]
pub fn project<T: RealNumber>(
obj: &TVec3<T>,
model: &TMat4<T>,
@ -68,11 +66,11 @@ pub fn project<T: RealNumber>(
///
/// # See also:
///
/// * [`project`](fn.project.html)
/// * [`project_zo`](fn.project_zo.html)
/// * [`unproject`](fn.unproject.html)
/// * [`unproject_no`](fn.unproject_no.html)
/// * [`unproject_zo`](fn.unproject_zo.html)
/// * [`project()`]
/// * [`project_zo()`]
/// * [`unproject()`]
/// * [`unproject_no()`]
/// * [`unproject_zo()`]
pub fn project_no<T: RealNumber>(
obj: &TVec3<T>,
model: &TMat4<T>,
@ -96,11 +94,11 @@ pub fn project_no<T: RealNumber>(
///
/// # See also:
///
/// * [`project`](fn.project.html)
/// * [`project_no`](fn.project_no.html)
/// * [`unproject`](fn.unproject.html)
/// * [`unproject_no`](fn.unproject_no.html)
/// * [`unproject_zo`](fn.unproject_zo.html)
/// * [`project()`]
/// * [`project_no()`]
/// * [`unproject()`]
/// * [`unproject_no()`]
/// * [`unproject_zo()`]
pub fn project_zo<T: RealNumber>(
obj: &TVec3<T>,
model: &TMat4<T>,
@ -129,11 +127,11 @@ pub fn project_zo<T: RealNumber>(
///
/// # See also:
///
/// * [`project`](fn.project.html)
/// * [`project_no`](fn.project_no.html)
/// * [`project_zo`](fn.project_zo.html)
/// * [`unproject_no`](fn.unproject_no.html)
/// * [`unproject_zo`](fn.unproject_zo.html)
/// * [`project()`]
/// * [`project_no()`]
/// * [`project_zo()`]
/// * [`unproject_no()`]
/// * [`unproject_zo()`]
pub fn unproject<T: RealNumber>(
win: &TVec3<T>,
model: &TMat4<T>,
@ -156,11 +154,11 @@ pub fn unproject<T: RealNumber>(
///
/// # See also:
///
/// * [`project`](fn.project.html)
/// * [`project_no`](fn.project_no.html)
/// * [`project_zo`](fn.project_zo.html)
/// * [`unproject`](fn.unproject.html)
/// * [`unproject_zo`](fn.unproject_zo.html)
/// * [`project()`]
/// * [`project_no()`]
/// * [`project_zo()`]
/// * [`unproject()`]
/// * [`unproject_zo()`]
pub fn unproject_no<T: RealNumber>(
win: &TVec3<T>,
model: &TMat4<T>,
@ -193,11 +191,11 @@ pub fn unproject_no<T: RealNumber>(
///
/// # See also:
///
/// * [`project`](fn.project.html)
/// * [`project_no`](fn.project_no.html)
/// * [`project_zo`](fn.project_zo.html)
/// * [`unproject`](fn.unproject.html)
/// * [`unproject_no`](fn.unproject_no.html)
/// * [`project()`]
/// * [`project_no()`]
/// * [`project_zo()`]
/// * [`unproject()`]
/// * [`unproject_no()`]
pub fn unproject_zo<T: RealNumber>(
win: &TVec3<T>,
model: &TMat4<T>,

View File

@ -18,8 +18,8 @@ pub fn identity<T: Number, const D: usize>() -> TMat<T, D, D> {
///
/// # See also:
///
/// * [`look_at_lh`](fn.look_at_lh.html)
/// * [`look_at_rh`](fn.look_at_rh.html)
/// * [`look_at_lh()`]
/// * [`look_at_rh()`]
pub fn look_at<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T>) -> TMat4<T> {
look_at_rh(eye, center, up)
}
@ -34,8 +34,8 @@ pub fn look_at<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T>)
///
/// # See also:
///
/// * [`look_at`](fn.look_at.html)
/// * [`look_at_rh`](fn.look_at_rh.html)
/// * [`look_at()`]
/// * [`look_at_rh()`]
pub fn look_at_lh<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T>) -> TMat4<T> {
TMat::look_at_lh(&Point3::from(*eye), &Point3::from(*center), up)
}
@ -50,8 +50,8 @@ pub fn look_at_lh<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T
///
/// # See also:
///
/// * [`look_at`](fn.look_at.html)
/// * [`look_at_lh`](fn.look_at_lh.html)
/// * [`look_at()`]
/// * [`look_at_lh()`]
pub fn look_at_rh<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T>) -> TMat4<T> {
TMat::look_at_rh(&Point3::from(*eye), &Point3::from(*center), up)
}
@ -66,11 +66,11 @@ pub fn look_at_rh<T: RealNumber>(eye: &TVec3<T>, center: &TVec3<T>, up: &TVec3<T
///
/// # See also:
///
/// * [`rotate_x`](fn.rotate_x.html)
/// * [`rotate_y`](fn.rotate_y.html)
/// * [`rotate_z`](fn.rotate_z.html)
/// * [`scale`](fn.scale.html)
/// * [`translate`](fn.translate.html)
/// * [`rotate_x()`]
/// * [`rotate_y()`]
/// * [`rotate_z()`]
/// * [`scale()`]
/// * [`translate()`]
pub fn rotate<T: RealNumber>(m: &TMat4<T>, angle: T, axis: &TVec3<T>) -> TMat4<T> {
m * Rotation3::from_axis_angle(&Unit::new_normalize(*axis), angle).to_homogeneous()
}
@ -84,11 +84,11 @@ pub fn rotate<T: RealNumber>(m: &TMat4<T>, angle: T, axis: &TVec3<T>) -> TMat4<T
///
/// # See also:
///
/// * [`rotate`](fn.rotate.html)
/// * [`rotate_y`](fn.rotate_y.html)
/// * [`rotate_z`](fn.rotate_z.html)
/// * [`scale`](fn.scale.html)
/// * [`translate`](fn.translate.html)
/// * [`rotate()`]
/// * [`rotate_y()`]
/// * [`rotate_z()`]
/// * [`scale()`]
/// * [`translate()`]
pub fn rotate_x<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
rotate(m, angle, &TVec::x())
}
@ -102,11 +102,11 @@ pub fn rotate_x<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotate`](fn.rotate.html)
/// * [`rotate_x`](fn.rotate_x.html)
/// * [`rotate_z`](fn.rotate_z.html)
/// * [`scale`](fn.scale.html)
/// * [`translate`](fn.translate.html)
/// * [`rotate()`]
/// * [`rotate_x()`]
/// * [`rotate_z()`]
/// * [`scale()`]
/// * [`translate()`]
pub fn rotate_y<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
rotate(m, angle, &TVec::y())
}
@ -120,11 +120,11 @@ pub fn rotate_y<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotate`](fn.rotate.html)
/// * [`rotate_x`](fn.rotate_x.html)
/// * [`rotate_y`](fn.rotate_y.html)
/// * [`scale`](fn.scale.html)
/// * [`translate`](fn.translate.html)
/// * [`rotate()`]
/// * [`rotate_x()`]
/// * [`rotate_y()`]
/// * [`scale()`]
/// * [`translate()`]
pub fn rotate_z<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
rotate(m, angle, &TVec::z())
}
@ -138,11 +138,11 @@ pub fn rotate_z<T: RealNumber>(m: &TMat4<T>, angle: T) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotate`](fn.rotate.html)
/// * [`rotate_x`](fn.rotate_x.html)
/// * [`rotate_y`](fn.rotate_y.html)
/// * [`rotate_z`](fn.rotate_z.html)
/// * [`translate`](fn.translate.html)
/// * [`rotate()`]
/// * [`rotate_x()`]
/// * [`rotate_y()`]
/// * [`rotate_z()`]
/// * [`translate()`]
pub fn scale<T: Number>(m: &TMat4<T>, v: &TVec3<T>) -> TMat4<T> {
m.prepend_nonuniform_scaling(v)
}
@ -156,11 +156,11 @@ pub fn scale<T: Number>(m: &TMat4<T>, v: &TVec3<T>) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotate`](fn.rotate.html)
/// * [`rotate_x`](fn.rotate_x.html)
/// * [`rotate_y`](fn.rotate_y.html)
/// * [`rotate_z`](fn.rotate_z.html)
/// * [`scale`](fn.scale.html)
/// * [`rotate()`]
/// * [`rotate_x()`]
/// * [`rotate_y()`]
/// * [`rotate_z()`]
/// * [`scale()`]
pub fn translate<T: Number>(m: &TMat4<T>, v: &TVec3<T>) -> TMat4<T> {
m.prepend_translation(v)
}

View File

@ -1,4 +1,4 @@
use na::{self, Unit};
use na::Unit;
use crate::aliases::Qua;
use crate::RealNumber;

View File

@ -12,9 +12,9 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
/// * [`max4_scalar()`]
/// * [`min3_scalar()`]
/// * [`min4_scalar()`]
pub fn max2_scalar<T: Number>(a: T, b: T) -> T {
if a >= b {
a
@ -35,9 +35,9 @@ pub fn max2_scalar<T: Number>(a: T, b: T) -> T {
///
/// # See also:
///
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
/// * [`max4_scalar()`]
/// * [`min3_scalar()`]
/// * [`min4_scalar()`]
pub fn min2_scalar<T: Number>(a: T, b: T) -> T {
if a <= b {
a
@ -58,9 +58,9 @@ pub fn min2_scalar<T: Number>(a: T, b: T) -> T {
///
/// # See also:
///
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
/// * [`max4_scalar()`]
/// * [`min3_scalar()`]
/// * [`min4_scalar()`]
pub fn max3_scalar<T: Number>(a: T, b: T, c: T) -> T {
max2_scalar(max2_scalar(a, b), c)
}
@ -77,9 +77,9 @@ pub fn max3_scalar<T: Number>(a: T, b: T, c: T) -> T {
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
/// * [`max3_scalar()`]
/// * [`min3_scalar()`]
/// * [`min4_scalar()`]
pub fn max4_scalar<T: Number>(a: T, b: T, c: T, d: T) -> T {
max2_scalar(max2_scalar(a, b), max2_scalar(c, d))
}
@ -96,9 +96,9 @@ pub fn max4_scalar<T: Number>(a: T, b: T, c: T, d: T) -> T {
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min4_scalar`](fn.min4_scalar.html)
/// * [`max3_scalar()`]
/// * [`max4_scalar()`]
/// * [`min4_scalar()`]
pub fn min3_scalar<T: Number>(a: T, b: T, c: T) -> T {
min2_scalar(min2_scalar(a, b), c)
}
@ -115,9 +115,9 @@ pub fn min3_scalar<T: Number>(a: T, b: T, c: T) -> T {
///
/// # See also:
///
/// * [`max3_scalar`](fn.max3_scalar.html)
/// * [`max4_scalar`](fn.max4_scalar.html)
/// * [`min3_scalar`](fn.min3_scalar.html)
/// * [`max3_scalar()`]
/// * [`max4_scalar()`]
/// * [`min3_scalar()`]
pub fn min4_scalar<T: Number>(a: T, b: T, c: T, d: T) -> T {
min2_scalar(min2_scalar(a, b), min2_scalar(c, d))
}

View File

@ -10,18 +10,18 @@ pub fn epsilon<T: AbsDiffEq<Epsilon = T>>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`](crate::four_over_pi)
/// * [`half_pi()`](crate::half_pi)
/// * [`one_over_pi()`](crate::one_over_pi)
/// * [`one_over_two_pi()`](crate::one_over_two_pi)
/// * [`quarter_pi()`](crate::quarter_pi)
/// * [`root_half_pi()`](crate::root_half_pi)
/// * [`root_pi()`](crate::root_pi)
/// * [`root_two_pi()`](crate::root_two_pi)
/// * [`three_over_two_pi()`](crate::three_over_two_pi)
/// * [`two_over_pi()`](crate::two_over_pi)
/// * [`two_over_root_pi()`](crate::two_over_root_pi)
/// * [`two_pi()`](crate::two_pi)
pub fn pi<T: RealNumber>() -> T {
T::pi()
}

View File

@ -5,15 +5,15 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max2()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn max<T: Number, const D: usize>(a: &TVec<T, D>, b: T) -> TVec<T, D> {
a.map(|a| crate::max2_scalar(a, b))
}
@ -22,15 +22,15 @@ pub fn max<T: Number, const D: usize>(a: &TVec<T, D>, b: T) -> TVec<T, D> {
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn max2<T: Number, const D: usize>(a: &TVec<T, D>, b: &TVec<T, D>) -> TVec<T, D> {
a.zip_map(b, |a, b| crate::max2_scalar(a, b))
}
@ -39,15 +39,15 @@ pub fn max2<T: Number, const D: usize>(a: &TVec<T, D>, b: &TVec<T, D>) -> TVec<T
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn max3<T: Number, const D: usize>(
a: &TVec<T, D>,
b: &TVec<T, D>,
@ -60,15 +60,15 @@ pub fn max3<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max3()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn max4<T: Number, const D: usize>(
a: &TVec<T, D>,
b: &TVec<T, D>,
@ -82,15 +82,15 @@ pub fn max4<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min2()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn min<T: Number, const D: usize>(x: &TVec<T, D>, y: T) -> TVec<T, D> {
x.map(|x| crate::min2_scalar(x, y))
}
@ -99,15 +99,15 @@ pub fn min<T: Number, const D: usize>(x: &TVec<T, D>, y: T) -> TVec<T, D> {
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min3()`]
/// * [`min4()`]
pub fn min2<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<T, D> {
x.zip_map(y, |a, b| crate::min2_scalar(a, b))
}
@ -116,15 +116,15 @@ pub fn min2<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<T
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min4()`]
pub fn min3<T: Number, const D: usize>(
a: &TVec<T, D>,
b: &TVec<T, D>,
@ -137,15 +137,15 @@ pub fn min3<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`comp_max()`](crate::comp_max)
/// * [`comp_min()`](crate::comp_min)
/// * [`max()`]
/// * [`max2()`]
/// * [`max3()`]
/// * [`max4()`]
/// * [`min()`]
/// * [`min2()`]
/// * [`min3()`]
pub fn min4<T: Number, const D: usize>(
a: &TVec<T, D>,
b: &TVec<T, D>,

View File

@ -5,9 +5,9 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`equal_eps_vec`](fn.equal_eps_vec.html)
/// * [`not_equal_eps`](fn.not_equal_eps.html)
/// * [`not_equal_eps_vec`](fn.not_equal_eps_vec.html)
/// * [`equal_eps_vec()`]
/// * [`not_equal_eps()`]
/// * [`not_equal_eps_vec()`]
pub fn equal_eps<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
@ -20,9 +20,9 @@ pub fn equal_eps<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`equal_eps`](fn.equal_eps.html)
/// * [`not_equal_eps`](fn.not_equal_eps.html)
/// * [`not_equal_eps_vec`](fn.not_equal_eps_vec.html)
/// * [`equal_eps()`]
/// * [`not_equal_eps()`]
/// * [`not_equal_eps_vec()`]
pub fn equal_eps_vec<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
@ -35,9 +35,9 @@ pub fn equal_eps_vec<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`equal_eps`](fn.equal_eps.html)
/// * [`equal_eps_vec`](fn.equal_eps_vec.html)
/// * [`not_equal_eps_vec`](fn.not_equal_eps_vec.html)
/// * [`equal_eps()`]
/// * [`equal_eps_vec()`]
/// * [`not_equal_eps_vec()`]
pub fn not_equal_eps<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
@ -50,9 +50,9 @@ pub fn not_equal_eps<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`equal_eps`](fn.equal_eps.html)
/// * [`equal_eps_vec`](fn.equal_eps_vec.html)
/// * [`not_equal_eps`](fn.not_equal_eps.html)
/// * [`equal_eps()`]
/// * [`equal_eps_vec()`]
/// * [`not_equal_eps()`]
pub fn not_equal_eps_vec<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,

View File

@ -12,7 +12,7 @@ pub fn cross<T: Number>(x: &TVec3<T>, y: &TVec3<T>) -> TVec3<T> {
///
/// # See also:
///
/// * [`distance2`](fn.distance2.html)
/// * [`distance2()`](crate::distance2)
pub fn distance<T: RealNumber, const D: usize>(p0: &TVec<T, D>, p1: &TVec<T, D>) -> T {
(p1 - p0).norm()
}
@ -37,13 +37,13 @@ pub fn faceforward<T: Number, const D: usize>(
/// The magnitude of a vector.
///
/// A synonym for [`magnitude`](fn.magnitude.html).
/// A synonym for [`magnitude()`].
///
/// # See also:
///
/// * [`length2`](fn.length2.html)
/// * [`magnitude`](fn.magnitude.html)
/// * [`magnitude2`](fn.magnitude2.html)
/// * [`length2()`](crate::length2)
/// * [`magnitude()`]
/// * [`magnitude2()`](crate::magnitude2)
pub fn length<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
x.norm()
}
@ -54,8 +54,8 @@ pub fn length<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
///
/// # See also:
///
/// * [`length`](fn.length.html)
/// * [`magnitude2`](fn.magnitude2.html)
/// * [`length()`]
/// * [`magnitude2()`](crate::magnitude2)
/// * [`nalgebra::norm`](../nalgebra/fn.norm.html)
pub fn magnitude<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
x.norm()

View File

@ -1,9 +1,8 @@
use crate::RealNumber;
use na;
/// The Euler constant.
///
/// This is a shorthand alias for [`euler`](fn.euler.html).
/// This is a shorthand alias for [`euler()`].
pub fn e<T: RealNumber>() -> T {
T::e()
}
@ -17,18 +16,18 @@ pub fn euler<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn four_over_pi<T: RealNumber>() -> T {
na::convert::<_, T>(4.0) / T::pi()
}
@ -42,18 +41,18 @@ pub fn golden_ratio<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn half_pi<T: RealNumber>() -> T {
T::frac_pi_2()
}
@ -62,8 +61,8 @@ pub fn half_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`ln_ten`](fn.ln_ten.html)
/// * [`ln_two`](fn.ln_two.html)
/// * [`ln_ten()`]
/// * [`ln_two()`]
pub fn ln_ln_two<T: RealNumber>() -> T {
T::ln_2().ln()
}
@ -72,8 +71,8 @@ pub fn ln_ln_two<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`ln_ln_two`](fn.ln_ln_two.html)
/// * [`ln_two`](fn.ln_two.html)
/// * [`ln_ln_two()`]
/// * [`ln_two()`]
pub fn ln_ten<T: RealNumber>() -> T {
T::ln_10()
}
@ -82,8 +81,8 @@ pub fn ln_ten<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`ln_ln_two`](fn.ln_ln_two.html)
/// * [`ln_ten`](fn.ln_ten.html)
/// * [`ln_ln_two()`]
/// * [`ln_ten()`]
pub fn ln_two<T: RealNumber>() -> T {
T::ln_2()
}
@ -95,18 +94,18 @@ pub use na::one;
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn one_over_pi<T: RealNumber>() -> T {
T::frac_1_pi()
}
@ -120,18 +119,18 @@ pub fn one_over_root_two<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn one_over_two_pi<T: RealNumber>() -> T {
T::frac_1_pi() * na::convert(0.5)
}
@ -140,18 +139,18 @@ pub fn one_over_two_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn quarter_pi<T: RealNumber>() -> T {
T::frac_pi_4()
}
@ -160,8 +159,8 @@ pub fn quarter_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`root_three`](fn.root_three.html)
/// * [`root_two`](fn.root_two.html)
/// * [`root_three()`]
/// * [`root_two()`]
pub fn root_five<T: RealNumber>() -> T {
na::convert::<_, T>(5.0).sqrt()
}
@ -170,18 +169,18 @@ pub fn root_five<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn root_half_pi<T: RealNumber>() -> T {
(T::pi() / na::convert(2.0)).sqrt()
}
@ -195,18 +194,18 @@ pub fn root_ln_four<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn root_pi<T: RealNumber>() -> T {
T::pi().sqrt()
}
@ -215,8 +214,8 @@ pub fn root_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`root_five`](fn.root_five.html)
/// * [`root_two`](fn.root_two.html)
/// * [`root_five()`]
/// * [`root_two()`]
pub fn root_three<T: RealNumber>() -> T {
na::convert::<_, T>(3.0).sqrt()
}
@ -225,8 +224,8 @@ pub fn root_three<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`root_five`](fn.root_five.html)
/// * [`root_three`](fn.root_three.html)
/// * [`root_five()`]
/// * [`root_three()`]
pub fn root_two<T: RealNumber>() -> T {
// TODO: there should be a crate::sqrt_2() on the RealNumber trait.
na::convert::<_, T>(2.0).sqrt()
@ -236,18 +235,18 @@ pub fn root_two<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn root_two_pi<T: RealNumber>() -> T {
T::two_pi().sqrt()
}
@ -256,7 +255,7 @@ pub fn root_two_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`two_thirds`](fn.two_thirds.html)
/// * [`two_thirds()`]
pub fn third<T: RealNumber>() -> T {
na::convert(1.0 / 3.0)
}
@ -265,18 +264,18 @@ pub fn third<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn three_over_two_pi<T: RealNumber>() -> T {
na::convert::<_, T>(3.0) / T::two_pi()
}
@ -285,17 +284,18 @@ pub fn three_over_two_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_root_pi()`]
/// * [`two_pi()`]
pub fn two_over_pi<T: RealNumber>() -> T {
T::frac_2_pi()
}
@ -304,18 +304,18 @@ pub fn two_over_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_pi`](fn.two_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_pi()`]
pub fn two_over_root_pi<T: RealNumber>() -> T {
T::frac_2_sqrt_pi()
}
@ -324,18 +324,18 @@ pub fn two_over_root_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`four_over_pi`](fn.four_over_pi.html)
/// * [`half_pi`](fn.half_pi.html)
/// * [`one_over_pi`](fn.one_over_pi.html)
/// * [`one_over_two_pi`](fn.one_over_two_pi.html)
/// * [`pi`](fn.pi.html)
/// * [`quarter_pi`](fn.quarter_pi.html)
/// * [`root_half_pi`](fn.root_half_pi.html)
/// * [`root_pi`](fn.root_pi.html)
/// * [`root_two_pi`](fn.root_two_pi.html)
/// * [`three_over_two_pi`](fn.three_over_two_pi.html)
/// * [`two_over_pi`](fn.two_over_pi.html)
/// * [`two_over_root_pi`](fn.two_over_root_pi.html)
/// * [`four_over_pi()`]
/// * [`half_pi()`]
/// * [`one_over_pi()`]
/// * [`one_over_two_pi()`]
/// * [`pi()`](crate::pi)
/// * [`quarter_pi()`]
/// * [`root_half_pi()`]
/// * [`root_pi()`]
/// * [`root_two_pi()`]
/// * [`three_over_two_pi()`]
/// * [`two_over_pi()`]
/// * [`two_over_root_pi()`]
pub fn two_pi<T: RealNumber>() -> T {
T::two_pi()
}
@ -344,7 +344,7 @@ pub fn two_pi<T: RealNumber>() -> T {
///
/// # See also:
///
/// * [`third`](fn.third.html)
/// * [`third()`]
pub fn two_thirds<T: RealNumber>() -> T {
na::convert(2.0 / 3.0)
}

View File

@ -7,24 +7,24 @@ use na::DefaultAllocator;
use crate::traits::{Alloc, Number, Dimension};
use crate::aliases::TVec;
/// Component-wise approximate equality beween two vectors.
/// Component-wise approximate equality between two vectors.
pub fn epsilon_equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, epsilon: T) -> TVec<bool, D>
where DefaultAllocator: Alloc<T, D> {
x.zip_map(y, |x, y| abs_diff_eq!(x, y, epsilon = epsilon))
}
/// Component-wise approximate equality beween two scalars.
/// Component-wise approximate equality between two scalars.
pub fn epsilon_equal2<T: AbsDiffEq<Epsilon = T>>(x: T, y: T, epsilon: T) -> bool {
abs_diff_eq!(x, y, epsilon = epsilon)
}
/// Component-wise approximate non-equality beween two vectors.
/// Component-wise approximate non-equality between two vectors.
pub fn epsilon_not_equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>, epsilon: T) -> TVec<bool, D>
where DefaultAllocator: Alloc<T, D> {
x.zip_map(y, |x, y| abs_diff_ne!(x, y, epsilon = epsilon))
}
/// Component-wise approximate non-equality beween two scalars.
/// Component-wise approximate non-equality between two scalars.
pub fn epsilon_not_equal2<T: AbsDiffEq<Epsilon = T>>(x: T, y: T, epsilon: T) -> bool {
abs_diff_ne!(x, y, epsilon = epsilon)
}

View File

@ -6,9 +6,9 @@ use crate::aliases::{TMat, TVec};
///
/// # See also:
///
/// * [`row`](fn.row.html)
/// * [`set_column`](fn.set_column.html)
/// * [`set_row`](fn.set_row.html)
/// * [`row()`]
/// * [`set_column()`]
/// * [`set_row()`]
pub fn column<T: Scalar, const R: usize, const C: usize>(
m: &TMat<T, R, C>,
index: usize,
@ -20,9 +20,9 @@ pub fn column<T: Scalar, const R: usize, const C: usize>(
///
/// # See also:
///
/// * [`column`](fn.column.html)
/// * [`row`](fn.row.html)
/// * [`set_row`](fn.set_row.html)
/// * [`column()`]
/// * [`row()`]
/// * [`set_row()`]
pub fn set_column<T: Scalar, const R: usize, const C: usize>(
m: &TMat<T, R, C>,
index: usize,
@ -37,9 +37,9 @@ pub fn set_column<T: Scalar, const R: usize, const C: usize>(
///
/// # See also:
///
/// * [`column`](fn.column.html)
/// * [`set_column`](fn.set_column.html)
/// * [`set_row`](fn.set_row.html)
/// * [`column()`]
/// * [`set_column()`]
/// * [`set_row()`]
pub fn row<T: Scalar, const R: usize, const C: usize>(
m: &TMat<T, R, C>,
index: usize,
@ -51,9 +51,9 @@ pub fn row<T: Scalar, const R: usize, const C: usize>(
///
/// # See also:
///
/// * [`column`](fn.column.html)
/// * [`row`](fn.row.html)
/// * [`set_column`](fn.set_column.html)
/// * [`column()`]
/// * [`row()`]
/// * [`set_column()`]
pub fn set_row<T: Scalar, const R: usize, const C: usize>(
m: &TMat<T, R, C>,
index: usize,

View File

@ -128,9 +128,9 @@ pub fn make_quat<T: RealNumber>(ptr: &[T]) -> Qua<T> {
///
/// # See also:
///
/// * [`make_vec2`](fn.make_vec2.html)
/// * [`make_vec3`](fn.make_vec3.html)
/// * [`make_vec4`](fn.make_vec4.html)
/// * [`make_vec2()`]
/// * [`make_vec3()`]
/// * [`make_vec4()`]
pub fn make_vec1<T: Scalar>(v: &TVec1<T>) -> TVec1<T> {
v.clone()
}
@ -139,12 +139,11 @@ pub fn make_vec1<T: Scalar>(v: &TVec1<T>) -> TVec1<T> {
///
/// # See also:
///
/// * [`vec1_to_vec1`](fn.vec1_to_vec1.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec4_to_vec1`](fn.vec4_to_vec1.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec3_to_vec1()`]
/// * [`vec4_to_vec1()`]
/// * [`vec1_to_vec2()`]
/// * [`vec1_to_vec3()`]
/// * [`vec1_to_vec4()`]
pub fn vec2_to_vec1<T: Scalar>(v: &TVec2<T>) -> TVec1<T> {
TVec1::new(v.x.clone())
}
@ -153,12 +152,11 @@ pub fn vec2_to_vec1<T: Scalar>(v: &TVec2<T>) -> TVec1<T> {
///
/// # See also:
///
/// * [`vec1_to_vec1`](fn.vec1_to_vec1.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec4_to_vec1`](fn.vec4_to_vec1.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec1()`]
/// * [`vec4_to_vec1()`]
/// * [`vec1_to_vec2()`]
/// * [`vec1_to_vec3()`]
/// * [`vec1_to_vec4()`]
pub fn vec3_to_vec1<T: Scalar>(v: &TVec3<T>) -> TVec1<T> {
TVec1::new(v.x.clone())
}
@ -167,12 +165,11 @@ pub fn vec3_to_vec1<T: Scalar>(v: &TVec3<T>) -> TVec1<T> {
///
/// # See also:
///
/// * [`vec1_to_vec1`](fn.vec1_to_vec1.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec1()`]
/// * [`vec3_to_vec1()`]
/// * [`vec1_to_vec2()`]
/// * [`vec1_to_vec3()`]
/// * [`vec1_to_vec4()`]
pub fn vec4_to_vec1<T: Scalar>(v: &TVec4<T>) -> TVec1<T> {
TVec1::new(v.x.clone())
}
@ -183,12 +180,12 @@ pub fn vec4_to_vec1<T: Scalar>(v: &TVec4<T>) -> TVec1<T> {
///
/// # See also:
///
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec4_to_vec2`](fn.vec4_to_vec2.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec2_to_vec2`](fn.vec2_to_vec2.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec3_to_vec2()`]
/// * [`vec4_to_vec2()`]
/// * [`vec2_to_vec1()`]
/// * [`vec2_to_vec2()`]
/// * [`vec2_to_vec3()`]
/// * [`vec2_to_vec4()`]
pub fn vec1_to_vec2<T: Number>(v: &TVec1<T>) -> TVec2<T> {
TVec2::new(v.x.clone(), T::zero())
}
@ -197,13 +194,13 @@ pub fn vec1_to_vec2<T: Number>(v: &TVec1<T>) -> TVec2<T> {
///
/// # See also:
///
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec4_to_vec2`](fn.vec4_to_vec2.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec2_to_vec2`](fn.vec2_to_vec2.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec1_to_vec2()`]
/// * [`vec3_to_vec2()`]
/// * [`vec4_to_vec2()`]
/// * [`vec2_to_vec1()`]
/// * [`vec2_to_vec2()`]
/// * [`vec2_to_vec3()`]
/// * [`vec2_to_vec4()`]
pub fn vec2_to_vec2<T: Scalar>(v: &TVec2<T>) -> TVec2<T> {
v.clone()
}
@ -212,12 +209,12 @@ pub fn vec2_to_vec2<T: Scalar>(v: &TVec2<T>) -> TVec2<T> {
///
/// # See also:
///
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec4_to_vec2`](fn.vec4_to_vec2.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec2_to_vec2`](fn.vec2_to_vec2.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec1_to_vec2()`]
/// * [`vec4_to_vec2()`]
/// * [`vec2_to_vec1()`]
/// * [`vec2_to_vec2()`]
/// * [`vec2_to_vec3()`]
/// * [`vec2_to_vec4()`]
pub fn vec3_to_vec2<T: Scalar>(v: &TVec3<T>) -> TVec2<T> {
TVec2::new(v.x.clone(), v.y.clone())
}
@ -226,12 +223,12 @@ pub fn vec3_to_vec2<T: Scalar>(v: &TVec3<T>) -> TVec2<T> {
///
/// # See also:
///
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec3_to_vec2`](fn.vec4_to_vec2.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec2_to_vec2`](fn.vec2_to_vec2.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec1_to_vec2()`]
/// * [`vec3_to_vec2()`]
/// * [`vec2_to_vec1()`]
/// * [`vec2_to_vec2()`]
/// * [`vec2_to_vec3()`]
/// * [`vec2_to_vec4()`]
pub fn vec4_to_vec2<T: Scalar>(v: &TVec4<T>) -> TVec2<T> {
TVec2::new(v.x.clone(), v.y.clone())
}
@ -240,9 +237,9 @@ pub fn vec4_to_vec2<T: Scalar>(v: &TVec4<T>) -> TVec2<T> {
///
/// # See also:
///
/// * [`make_vec1`](fn.make_vec1.html)
/// * [`make_vec3`](fn.make_vec3.html)
/// * [`make_vec4`](fn.make_vec4.html)
/// * [`make_vec1()`]
/// * [`make_vec3()`]
/// * [`make_vec4()`]
pub fn make_vec2<T: Scalar>(ptr: &[T]) -> TVec2<T> {
TVec2::from_column_slice(ptr)
}
@ -253,11 +250,11 @@ pub fn make_vec2<T: Scalar>(ptr: &[T]) -> TVec2<T> {
///
/// # See also:
///
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec3_to_vec3`](fn.vec3_to_vec3.html)
/// * [`vec4_to_vec3`](fn.vec4_to_vec3.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec3()`]
/// * [`vec3_to_vec3()`]
/// * [`vec4_to_vec3()`]
/// * [`vec1_to_vec2()`]
/// * [`vec1_to_vec4()`]
pub fn vec1_to_vec3<T: Number>(v: &TVec1<T>) -> TVec3<T> {
TVec3::new(v.x.clone(), T::zero(), T::zero())
}
@ -268,12 +265,12 @@ pub fn vec1_to_vec3<T: Number>(v: &TVec1<T>) -> TVec3<T> {
///
/// # See also:
///
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec3_to_vec3`](fn.vec3_to_vec3.html)
/// * [`vec4_to_vec3`](fn.vec4_to_vec3.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec1_to_vec3()`]
/// * [`vec3_to_vec3()`]
/// * [`vec4_to_vec3()`]
/// * [`vec3_to_vec1()`]
/// * [`vec3_to_vec2()`]
/// * [`vec3_to_vec4()`]
pub fn vec2_to_vec3<T: Number>(v: &TVec2<T>) -> TVec3<T> {
TVec3::new(v.x.clone(), v.y.clone(), T::zero())
}
@ -282,12 +279,12 @@ pub fn vec2_to_vec3<T: Number>(v: &TVec2<T>) -> TVec3<T> {
///
/// # See also:
///
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec4_to_vec3`](fn.vec4_to_vec3.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec1_to_vec3()`]
/// * [`vec2_to_vec3()`]
/// * [`vec4_to_vec3()`]
/// * [`vec3_to_vec1()`]
/// * [`vec3_to_vec2()`]
/// * [`vec3_to_vec4()`]
pub fn vec3_to_vec3<T: Scalar>(v: &TVec3<T>) -> TVec3<T> {
v.clone()
}
@ -296,12 +293,12 @@ pub fn vec3_to_vec3<T: Scalar>(v: &TVec3<T>) -> TVec3<T> {
///
/// # See also:
///
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec3_to_vec3`](fn.vec3_to_vec3.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec1_to_vec3()`]
/// * [`vec2_to_vec3()`]
/// * [`vec3_to_vec3()`]
/// * [`vec3_to_vec1()`]
/// * [`vec3_to_vec2()`]
/// * [`vec3_to_vec4()`]
pub fn vec4_to_vec3<T: Scalar>(v: &TVec4<T>) -> TVec3<T> {
TVec3::new(v.x.clone(), v.y.clone(), v.z.clone())
}
@ -310,9 +307,9 @@ pub fn vec4_to_vec3<T: Scalar>(v: &TVec4<T>) -> TVec3<T> {
///
/// # See also:
///
/// * [`make_vec1`](fn.make_vec1.html)
/// * [`make_vec2`](fn.make_vec2.html)
/// * [`make_vec4`](fn.make_vec4.html)
/// * [`make_vec1()`]
/// * [`make_vec2()`]
/// * [`make_vec4()`]
pub fn make_vec3<T: Scalar>(ptr: &[T]) -> TVec3<T> {
TVec3::from_column_slice(ptr)
}
@ -323,12 +320,12 @@ pub fn make_vec3<T: Scalar>(ptr: &[T]) -> TVec3<T> {
///
/// # See also:
///
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec4_to_vec4`](fn.vec4_to_vec4.html)
/// * [`vec1_to_vec2`](fn.vec1_to_vec2.html)
/// * [`vec1_to_vec3`](fn.vec1_to_vec3.html)
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec4()`]
/// * [`vec3_to_vec4()`]
/// * [`vec4_to_vec4()`]
/// * [`vec1_to_vec2()`]
/// * [`vec1_to_vec3()`]
/// * [`vec1_to_vec4()`]
pub fn vec1_to_vec4<T: Number>(v: &TVec1<T>) -> TVec4<T> {
TVec4::new(v.x, T::zero(), T::zero(), T::zero())
}
@ -339,12 +336,12 @@ pub fn vec1_to_vec4<T: Number>(v: &TVec1<T>) -> TVec4<T> {
///
/// # See also:
///
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec4_to_vec4`](fn.vec4_to_vec4.html)
/// * [`vec2_to_vec1`](fn.vec2_to_vec1.html)
/// * [`vec2_to_vec2`](fn.vec2_to_vec2.html)
/// * [`vec2_to_vec3`](fn.vec2_to_vec3.html)
/// * [`vec1_to_vec4()`]
/// * [`vec3_to_vec4()`]
/// * [`vec4_to_vec4()`]
/// * [`vec2_to_vec1()`]
/// * [`vec2_to_vec2()`]
/// * [`vec2_to_vec3()`]
pub fn vec2_to_vec4<T: Number>(v: &TVec2<T>) -> TVec4<T> {
TVec4::new(v.x, v.y, T::zero(), T::zero())
}
@ -355,12 +352,12 @@ pub fn vec2_to_vec4<T: Number>(v: &TVec2<T>) -> TVec4<T> {
///
/// # See also:
///
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec4_to_vec4`](fn.vec4_to_vec4.html)
/// * [`vec3_to_vec1`](fn.vec3_to_vec1.html)
/// * [`vec3_to_vec2`](fn.vec3_to_vec2.html)
/// * [`vec3_to_vec3`](fn.vec3_to_vec3.html)
/// * [`vec1_to_vec4()`]
/// * [`vec2_to_vec4()`]
/// * [`vec4_to_vec4()`]
/// * [`vec3_to_vec1()`]
/// * [`vec3_to_vec2()`]
/// * [`vec3_to_vec3()`]
pub fn vec3_to_vec4<T: Number>(v: &TVec3<T>) -> TVec4<T> {
TVec4::new(v.x, v.y, v.z, T::zero())
}
@ -369,12 +366,12 @@ pub fn vec3_to_vec4<T: Number>(v: &TVec3<T>) -> TVec4<T> {
///
/// # See also:
///
/// * [`vec1_to_vec4`](fn.vec1_to_vec4.html)
/// * [`vec2_to_vec4`](fn.vec2_to_vec4.html)
/// * [`vec3_to_vec4`](fn.vec3_to_vec4.html)
/// * [`vec4_to_vec1`](fn.vec4_to_vec1.html)
/// * [`vec4_to_vec2`](fn.vec4_to_vec2.html)
/// * [`vec4_to_vec3`](fn.vec4_to_vec3.html)
/// * [`vec1_to_vec4()`]
/// * [`vec2_to_vec4()`]
/// * [`vec3_to_vec4()`]
/// * [`vec4_to_vec1()`]
/// * [`vec4_to_vec2()`]
/// * [`vec4_to_vec3()`]
pub fn vec4_to_vec4<T: Scalar>(v: &TVec4<T>) -> TVec4<T> {
v.clone()
}
@ -383,9 +380,9 @@ pub fn vec4_to_vec4<T: Scalar>(v: &TVec4<T>) -> TVec4<T> {
///
/// # See also:
///
/// * [`make_vec1`](fn.make_vec1.html)
/// * [`make_vec2`](fn.make_vec2.html)
/// * [`make_vec3`](fn.make_vec3.html)
/// * [`make_vec1()`]
/// * [`make_vec2()`]
/// * [`make_vec3()`]
pub fn make_vec4<T: Scalar>(ptr: &[T]) -> TVec4<T> {
TVec4::from_column_slice(ptr)
}

View File

@ -16,9 +16,9 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`comp_mul`](fn.comp_mul.html)
/// * [`comp_max()`]
/// * [`comp_min()`]
/// * [`comp_mul()`]
pub fn comp_add<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) -> T {
m.iter().fold(T::zero(), |x, y| x + *y)
}
@ -38,13 +38,13 @@ pub fn comp_add<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) ->
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`max`](fn.max.html)
/// * [`max2`](fn.max2.html)
/// * [`max3`](fn.max3.html)
/// * [`max4`](fn.max4.html)
/// * [`comp_add()`]
/// * [`comp_max()`]
/// * [`comp_min()`]
/// * [`max()`](crate::max)
/// * [`max2()`](crate::max2)
/// * [`max3()`](crate::max3)
/// * [`max4()`](crate::max4)
pub fn comp_max<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) -> T {
m.iter()
.fold(T::min_value(), |x, y| crate::max2_scalar(x, *y))
@ -65,13 +65,13 @@ pub fn comp_max<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) ->
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_mul`](fn.comp_mul.html)
/// * [`min`](fn.min.html)
/// * [`min2`](fn.min2.html)
/// * [`min3`](fn.min3.html)
/// * [`min4`](fn.min4.html)
/// * [`comp_add()`]
/// * [`comp_max()`]
/// * [`comp_mul()`]
/// * [`min()`](crate::min)
/// * [`min2()`](crate::min2)
/// * [`min3()`](crate::min3)
/// * [`min4()`](crate::min4)
pub fn comp_min<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) -> T {
m.iter()
.fold(T::max_value(), |x, y| crate::min2_scalar(x, *y))
@ -92,9 +92,9 @@ pub fn comp_min<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) ->
///
/// # See also:
///
/// * [`comp_add`](fn.comp_add.html)
/// * [`comp_max`](fn.comp_max.html)
/// * [`comp_min`](fn.comp_min.html)
/// * [`comp_add()`]
/// * [`comp_max()`]
/// * [`comp_min()`]
pub fn comp_mul<T: Number, const R: usize, const C: usize>(m: &TMat<T, R, C>) -> T {
m.iter().fold(T::one(), |x, y| x * *y)
}

View File

@ -5,7 +5,7 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`right_handed`](fn.right_handed.html)
/// * [`right_handed()`]
pub fn left_handed<T: Number>(a: &TVec3<T>, b: &TVec3<T>, c: &TVec3<T>) -> bool {
a.cross(b).dot(c) < T::zero()
}
@ -14,7 +14,7 @@ pub fn left_handed<T: Number>(a: &TVec3<T>, b: &TVec3<T>, c: &TVec3<T>) -> bool
///
/// # See also:
///
/// * [`left_handed`](fn.left_handed.html)
/// * [`left_handed()`]
pub fn right_handed<T: Number>(a: &TVec3<T>, b: &TVec3<T>, c: &TVec3<T>) -> bool {
a.cross(b).dot(c) > T::zero()
}

View File

@ -5,7 +5,7 @@ use crate::RealNumber;
///
/// # See also:
///
/// * [`matrix_cross`](fn.matrix_cross.html)
/// * [`matrix_cross()`]
pub fn matrix_cross3<T: RealNumber>(x: &TVec3<T>) -> TMat3<T> {
x.cross_matrix()
}
@ -14,7 +14,7 @@ pub fn matrix_cross3<T: RealNumber>(x: &TVec3<T>) -> TMat3<T> {
///
/// # See also:
///
/// * [`matrix_cross3`](fn.matrix_cross3.html)
/// * [`matrix_cross3()`]
pub fn matrix_cross<T: RealNumber>(x: &TVec3<T>) -> TMat4<T> {
crate::mat3_to_mat4(&x.cross_matrix())
}

View File

@ -7,14 +7,14 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal2x2<T: Number>(v: &TVec2<T>) -> TMat2<T> {
TMat2::from_diagonal(v)
}
@ -23,14 +23,14 @@ pub fn diagonal2x2<T: Number>(v: &TVec2<T>) -> TMat2<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal2x3<T: Number>(v: &TVec2<T>) -> TMat2x3<T> {
TMat2x3::from_partial_diagonal(v.as_slice())
}
@ -39,14 +39,14 @@ pub fn diagonal2x3<T: Number>(v: &TVec2<T>) -> TMat2x3<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal2x4<T: Number>(v: &TVec2<T>) -> TMat2x4<T> {
TMat2x4::from_partial_diagonal(v.as_slice())
}
@ -55,14 +55,14 @@ pub fn diagonal2x4<T: Number>(v: &TVec2<T>) -> TMat2x4<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal3x2<T: Number>(v: &TVec2<T>) -> TMat3x2<T> {
TMat3x2::from_partial_diagonal(v.as_slice())
}
@ -71,14 +71,14 @@ pub fn diagonal3x2<T: Number>(v: &TVec2<T>) -> TMat3x2<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal3x3<T: Number>(v: &TVec3<T>) -> TMat3<T> {
TMat3::from_diagonal(v)
}
@ -87,14 +87,14 @@ pub fn diagonal3x3<T: Number>(v: &TVec3<T>) -> TMat3<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal3x4<T: Number>(v: &TVec3<T>) -> TMat3x4<T> {
TMat3x4::from_partial_diagonal(v.as_slice())
}
@ -103,14 +103,14 @@ pub fn diagonal3x4<T: Number>(v: &TVec3<T>) -> TMat3x4<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x3()`]
/// * [`diagonal4x4()`]
pub fn diagonal4x2<T: Number>(v: &TVec2<T>) -> TMat4x2<T> {
TMat4x2::from_partial_diagonal(v.as_slice())
}
@ -119,14 +119,14 @@ pub fn diagonal4x2<T: Number>(v: &TVec2<T>) -> TMat4x2<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x4`](fn.diagonal4x4.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x4()`]
pub fn diagonal4x3<T: Number>(v: &TVec3<T>) -> TMat4x3<T> {
TMat4x3::from_partial_diagonal(v.as_slice())
}
@ -135,14 +135,14 @@ pub fn diagonal4x3<T: Number>(v: &TVec3<T>) -> TMat4x3<T> {
///
/// # See also:
///
/// * [`diagonal2x2`](fn.diagonal2x2.html)
/// * [`diagonal2x3`](fn.diagonal2x3.html)
/// * [`diagonal2x4`](fn.diagonal2x4.html)
/// * [`diagonal3x2`](fn.diagonal3x2.html)
/// * [`diagonal3x3`](fn.diagonal3x3.html)
/// * [`diagonal3x4`](fn.diagonal3x4.html)
/// * [`diagonal4x2`](fn.diagonal4x2.html)
/// * [`diagonal4x3`](fn.diagonal4x3.html)
/// * [`diagonal2x2()`]
/// * [`diagonal2x3()`]
/// * [`diagonal2x4()`]
/// * [`diagonal3x2()`]
/// * [`diagonal3x3()`]
/// * [`diagonal3x4()`]
/// * [`diagonal4x2()`]
/// * [`diagonal4x3()`]
pub fn diagonal4x4<T: Number>(v: &TVec4<T>) -> TMat4<T> {
TMat4::from_diagonal(v)
}

View File

@ -5,7 +5,7 @@ use crate::RealNumber;
///
/// # See also:
///
/// * [`distance`](fn.distance.html)
/// * [`distance()`](crate::distance)
pub fn distance2<T: RealNumber, const D: usize>(p0: &TVec<T, D>, p1: &TVec<T, D>) -> T {
(p1 - p0).norm_squared()
}
@ -14,9 +14,9 @@ pub fn distance2<T: RealNumber, const D: usize>(p0: &TVec<T, D>, p1: &TVec<T, D>
///
/// # See also:
///
/// * [`l1_norm`](fn.l1_norm.html)
/// * [`l2_distance`](fn.l2_distance.html)
/// * [`l2_norm`](fn.l2_norm.html)
/// * [`l1_norm()`]
/// * [`l2_distance()`]
/// * [`l2_norm()`]
pub fn l1_distance<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> T {
l1_norm(&(y - x))
}
@ -28,27 +28,27 @@ pub fn l1_distance<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>
///
/// # See also:
///
/// * [`l1_distance`](fn.l1_distance.html)
/// * [`l2_distance`](fn.l2_distance.html)
/// * [`l2_norm`](fn.l2_norm.html)
/// * [`l1_distance()`]
/// * [`l2_distance()`]
/// * [`l2_norm()`]
pub fn l1_norm<T: RealNumber, const D: usize>(v: &TVec<T, D>) -> T {
crate::comp_add(&v.abs())
}
/// The l2-norm of `x - y`.
///
/// This is the same value as returned by [`length2`](fn.length2.html) and
/// [`magnitude2`](fn.magnitude2.html).
/// This is the same value as returned by [`length2()`] and
/// [`magnitude2()`].
///
/// # See also:
///
/// * [`l1_distance`](fn.l1_distance.html)
/// * [`l1_norm`](fn.l1_norm.html)
/// * [`l2_norm`](fn.l2_norm.html)
/// * [`length`](fn.length.html)
/// * [`length2`](fn.length2.html)
/// * [`magnitude`](fn.magnitude.html)
/// * [`magnitude2`](fn.magnitude2.html)
/// * [`l1_distance()`]
/// * [`l1_norm()`]
/// * [`l2_norm()`]
/// * [`length()`](crate::length)
/// * [`length2()`]
/// * [`magnitude()`](crate::magnitude)
/// * [`magnitude2()`]
pub fn l2_distance<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> T {
l2_norm(&(y - x))
}
@ -57,33 +57,33 @@ pub fn l2_distance<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>
///
/// This is also known as the Euclidean norm.
///
/// This is the same value as returned by [`length`](fn.length.html) and
/// [`magnitude`](fn.magnitude.html).
/// This is the same value as returned by [`length()`](crate::length) and
/// [`magnitude()`](crate::magnitude).
///
/// # See also:
///
/// * [`l1_distance`](fn.l1_distance.html)
/// * [`l1_norm`](fn.l1_norm.html)
/// * [`l2_distance`](fn.l2_distance.html)
/// * [`length`](fn.length.html)
/// * [`length2`](fn.length2.html)
/// * [`magnitude`](fn.magnitude.html)
/// * [`magnitude2`](fn.magnitude2.html)
/// * [`l1_distance()`]
/// * [`l1_norm()`]
/// * [`l2_distance()`]
/// * [`length()`](crate::length)
/// * [`length2()`]
/// * [`magnitude()`](crate::magnitude)
/// * [`magnitude2()`]
pub fn l2_norm<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
x.norm()
}
/// The squared magnitude of `x`.
///
/// A synonym for [`magnitude2`](fn.magnitude2.html).
/// A synonym for [`magnitude2()`].
///
/// # See also:
///
/// * [`distance`](fn.distance.html)
/// * [`distance2`](fn.distance2.html)
/// * [`length`](fn.length.html)
/// * [`magnitude`](fn.magnitude.html)
/// * [`magnitude2`](fn.magnitude2.html)
/// * [`distance()`](crate::distance)
/// * [`distance2()`]
/// * [`length()`](crate::length)
/// * [`magnitude()`](crate::magnitude)
/// * [`magnitude2()`]
pub fn length2<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
x.norm_squared()
}
@ -94,10 +94,10 @@ pub fn length2<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
///
/// # See also:
///
/// * [`distance`](fn.distance.html)
/// * [`distance2`](fn.distance2.html)
/// * [`length2`](fn.length2.html)
/// * [`magnitude`](fn.magnitude.html)
/// * [`distance()`](crate::distance)
/// * [`distance2()`]
/// * [`length2()`]
/// * [`magnitude()`](crate::magnitude)
/// * [`nalgebra::norm_squared`](../nalgebra/fn.norm_squared.html)
pub fn magnitude2<T: RealNumber, const D: usize>(x: &TVec<T, D>) -> T {
x.norm_squared()

View File

@ -4,11 +4,11 @@ use crate::aliases::TVec;
/// The dot product of the normalized version of `x` and `y`.
///
/// This is currently the same as [`normalize_dot`](fn.normalize_dot.html).
/// This is currently the same as [`normalize_dot()`]
///
/// # See also:
///
/// * [`normalize_dot`](fn.normalize_dot.html`)
/// * [`normalize_dot()`]
pub fn fast_normalize_dot<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> T {
// XXX: improve those.
x.normalize().dot(&y.normalize())
@ -18,7 +18,7 @@ pub fn fast_normalize_dot<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVe
///
/// # See also:
///
/// * [`fast_normalize_dot`](fn.fast_normalize_dot.html`)
/// * [`fast_normalize_dot()`]
pub fn normalize_dot<T: RealNumber, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> T {
// XXX: improve those.
x.normalize().dot(&y.normalize())

View File

@ -80,7 +80,7 @@ pub fn quat_to_mat3<T: RealNumber>(x: &Qua<T>) -> TMat3<T> {
.into_inner()
}
/// Converts a quaternion to a rotation matrix in homogenous coordinates.
/// Converts a quaternion to a rotation matrix in homogeneous coordinates.
pub fn quat_to_mat4<T: RealNumber>(x: &Qua<T>) -> TMat4<T> {
UnitQuaternion::new_unchecked(*x).to_homogeneous()
}
@ -93,6 +93,6 @@ pub fn mat3_to_quat<T: RealNumber>(x: &TMat3<T>) -> Qua<T> {
/// Converts a rotation matrix in homogeneous coordinates to a quaternion.
pub fn to_quat<T: RealNumber>(x: &TMat4<T>) -> Qua<T> {
let rot = x.fixed_slice::<3, 3>(0, 0).into_owned();
let rot = x.fixed_view::<3, 3>(0, 0).into_owned();
mat3_to_quat(&rot)
}

View File

@ -7,11 +7,11 @@ use crate::traits::{Number, RealNumber};
///
/// # See also:
///
/// * [`scaling`](fn.scaling.html)
/// * [`translation`](fn.translation.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`scaling()`]
/// * [`translation()`]
/// * [`rotation2d()`]
/// * [`scaling2d()`]
/// * [`translation2d()`]
pub fn rotation<T: RealNumber>(angle: T, v: &TVec3<T>) -> TMat4<T> {
Rotation3::from_axis_angle(&Unit::new_normalize(*v), angle).to_homogeneous()
}
@ -20,11 +20,11 @@ pub fn rotation<T: RealNumber>(angle: T, v: &TVec3<T>) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotation`](fn.rotation.html)
/// * [`translation`](fn.translation.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotation()`]
/// * [`translation()`]
/// * [`rotation2d()`]
/// * [`scaling2d()`]
/// * [`translation2d()`]
pub fn scaling<T: Number>(v: &TVec3<T>) -> TMat4<T> {
TMat4::new_nonuniform_scaling(v)
}
@ -33,11 +33,11 @@ pub fn scaling<T: Number>(v: &TVec3<T>) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotation`](fn.rotation.html)
/// * [`scaling`](fn.scaling.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotation()`]
/// * [`scaling()`]
/// * [`rotation2d()`]
/// * [`scaling2d()`]
/// * [`translation2d()`]
pub fn translation<T: Number>(v: &TVec3<T>) -> TMat4<T> {
TMat4::new_translation(v)
}
@ -46,11 +46,11 @@ pub fn translation<T: Number>(v: &TVec3<T>) -> TMat4<T> {
///
/// # See also:
///
/// * [`rotation`](fn.rotation.html)
/// * [`scaling`](fn.scaling.html)
/// * [`translation`](fn.translation.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotation()`]
/// * [`scaling()`]
/// * [`translation()`]
/// * [`scaling2d()`]
/// * [`translation2d()`]
pub fn rotation2d<T: RealNumber>(angle: T) -> TMat3<T> {
Rotation2::new(angle).to_homogeneous()
}
@ -59,11 +59,11 @@ pub fn rotation2d<T: RealNumber>(angle: T) -> TMat3<T> {
///
/// # See also:
///
/// * [`rotation`](fn.rotation.html)
/// * [`scaling`](fn.scaling.html)
/// * [`translation`](fn.translation.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotation()`]
/// * [`scaling()`]
/// * [`translation()`]
/// * [`rotation2d()`]
/// * [`translation2d()`]
pub fn scaling2d<T: Number>(v: &TVec2<T>) -> TMat3<T> {
TMat3::new_nonuniform_scaling(v)
}
@ -72,11 +72,11 @@ pub fn scaling2d<T: Number>(v: &TVec2<T>) -> TMat3<T> {
///
/// # See also:
///
/// * [`rotation`](fn.rotation.html)
/// * [`scaling`](fn.scaling.html)
/// * [`translation`](fn.translation.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`rotation()`]
/// * [`scaling()`]
/// * [`translation()`]
/// * [`rotation2d()`]
/// * [`scaling2d()`]
pub fn translation2d<T: Number>(v: &TVec2<T>) -> TMat3<T> {
TMat3::new_translation(v)
}

View File

@ -7,7 +7,7 @@ pub fn proj2d<T: Number>(m: &TMat3<T>, normal: &TVec2<T>) -> TMat3<T> {
let mut res = TMat3::identity();
{
let mut part = res.fixed_slice_mut::<2, 2>(0, 0);
let mut part = res.fixed_view_mut::<2, 2>(0, 0);
part -= normal * normal.transpose();
}
@ -19,7 +19,7 @@ pub fn proj<T: Number>(m: &TMat4<T>, normal: &TVec3<T>) -> TMat4<T> {
let mut res = TMat4::identity();
{
let mut part = res.fixed_slice_mut::<3, 3>(0, 0);
let mut part = res.fixed_view_mut::<3, 3>(0, 0);
part -= normal * normal.transpose();
}
@ -31,7 +31,7 @@ pub fn reflect2d<T: RealNumber>(m: &TMat3<T>, normal: &TVec2<T>) -> TMat3<T> {
let mut res = TMat3::identity();
{
let mut part = res.fixed_slice_mut::<2, 2>(0, 0);
let mut part = res.fixed_view_mut::<2, 2>(0, 0);
part -= (normal * T::from_subset(&2.0)) * normal.transpose();
}
@ -43,7 +43,7 @@ pub fn reflect<T: RealNumber>(m: &TMat4<T>, normal: &TVec3<T>) -> TMat4<T> {
let mut res = TMat4::identity();
{
let mut part = res.fixed_slice_mut::<3, 3>(0, 0);
let mut part = res.fixed_view_mut::<3, 3>(0, 0);
part -= (normal * T::from_subset(&2.0)) * normal.transpose();
}

View File

@ -7,11 +7,11 @@ use crate::traits::{Number, RealNumber};
///
/// # See also:
///
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scale2d`](fn.scale2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translate2d`](fn.translate2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotation2d()`](crate::rotation2d)
/// * [`scale2d()`]
/// * [`scaling2d()`](crate::scaling2d)
/// * [`translate2d()`]
/// * [`translation2d()`](crate::translation2d)
pub fn rotate2d<T: RealNumber>(m: &TMat3<T>, angle: T) -> TMat3<T> {
m * UnitComplex::new(angle).to_homogeneous()
}
@ -20,11 +20,11 @@ pub fn rotate2d<T: RealNumber>(m: &TMat3<T>, angle: T) -> TMat3<T> {
///
/// # See also:
///
/// * [`rotate2d`](fn.rotate2d.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translate2d`](fn.translate2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotate2d()`]
/// * [`rotation2d()`](crate::rotation2d)
/// * [`scaling2d()`](crate::scaling2d)
/// * [`translate2d()`]
/// * [`translation2d()`](crate::translation2d)
pub fn scale2d<T: Number>(m: &TMat3<T>, v: &TVec2<T>) -> TMat3<T> {
m.prepend_nonuniform_scaling(v)
}
@ -33,11 +33,11 @@ pub fn scale2d<T: Number>(m: &TMat3<T>, v: &TVec2<T>) -> TMat3<T> {
///
/// # See also:
///
/// * [`rotate2d`](fn.rotate2d.html)
/// * [`rotation2d`](fn.rotation2d.html)
/// * [`scale2d`](fn.scale2d.html)
/// * [`scaling2d`](fn.scaling2d.html)
/// * [`translation2d`](fn.translation2d.html)
/// * [`rotate2d()`]
/// * [`rotation2d()`](crate::rotation2d)
/// * [`scale2d()`]
/// * [`scaling2d()`](crate::scaling2d)
/// * [`translation2d()`](crate::translation2d)
pub fn translate2d<T: Number>(m: &TMat3<T>, v: &TVec2<T>) -> TMat3<T> {
m.prepend_translation(v)
}

View File

@ -7,7 +7,7 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`are_collinear2d`](fn.are_collinear2d.html)
/// * [`are_collinear2d()`]
pub fn are_collinear<T: Number>(v0: &TVec3<T>, v1: &TVec3<T>, epsilon: T) -> bool {
is_null(&v0.cross(v1), epsilon)
}
@ -16,7 +16,7 @@ pub fn are_collinear<T: Number>(v0: &TVec3<T>, v1: &TVec3<T>, epsilon: T) -> boo
///
/// # See also:
///
/// * [`are_collinear`](fn.are_collinear.html)
/// * [`are_collinear()`]
pub fn are_collinear2d<T: Number>(v0: &TVec2<T>, v1: &TVec2<T>, epsilon: T) -> bool {
abs_diff_eq!(v0.perp(v1), T::zero(), epsilon = epsilon)
}
@ -41,7 +41,10 @@ pub fn is_comp_null<T: Number, const D: usize>(v: &TVec<T, D>, epsilon: T) -> TV
/// Returns `true` if `v` has a magnitude of 1 (up to an epsilon).
pub fn is_normalized<T: RealNumber, const D: usize>(v: &TVec<T, D>, epsilon: T) -> bool {
abs_diff_eq!(v.norm_squared(), T::one(), epsilon = epsilon * epsilon)
// sqrt(1 + epsilon_{norm²} = 1 + epsilon_{norm}
// ==> epsilon_{norm²} = epsilon_{norm}² + 2*epsilon_{norm}
// For small epsilon, epsilon² is basically zero, so use 2*epsilon.
abs_diff_eq!(v.norm_squared(), T::one(), epsilon = epsilon + epsilon)
}
/// Returns `true` if `v` is zero (up to an epsilon).

View File

@ -38,7 +38,7 @@
* All function names use `snake_case`, which is the Rust convention.
* All type names use `CamelCase`, which is the Rust convention.
* All function arguments, except for scalars, are all passed by-reference.
* The most generic vector and matrix types are [`TMat`](type.TMat.html) and [`TVec`](type.TVec.html) instead of `mat` and `vec`.
* The most generic vector and matrix types are [`TMat`] and [`TVec`] instead of `mat` and `vec`.
* Some feature are not yet implemented and should be added in the future. In particular, no packing
functions are available.
* A few features are not implemented and will never be. This includes functions related to color
@ -47,17 +47,17 @@
In addition, because Rust does not allows function overloading, all functions must be given a unique name.
Here are a few rules chosen arbitrarily for **nalgebra-glm**:
* Functions operating in 2d will usually end with the `2d` suffix, e.g., [`glm::rotate2d`](fn.rotate2d.html) is for 2D while [`glm::rotate`](fn.rotate.html) is for 3D.
* Functions operating on vectors will often end with the `_vec` suffix, possibly followed by the dimension of vector, e.g., [`glm::rotate_vec2`](fn.rotate_vec2.html).
* Every function related to quaternions start with the `quat_` prefix, e.g., [`glm::quat_dot(q1, q2)`](fn.quat_dot.html).
* Functions operating in 2d will usually end with the `2d` suffix, e.g., [`glm::rotate2d()`](crate::rotate2d) is for 2D while [`glm::rotate()`](crate::rotate) is for 3D.
* Functions operating on vectors will often end with the `_vec` suffix, possibly followed by the dimension of vector, e.g., [`glm::rotate_vec2()`](crate::rotate_vec2).
* Every function related to quaternions start with the `quat_` prefix, e.g., [`glm::quat_dot(q1, q2)`](crate::quat_dot).
* All the conversion functions have unique names as described [below](#conversions).
### Vector and matrix construction
Vectors, matrices, and quaternions can be constructed using several approaches:
* Using functions with the same name as their type in lower-case. For example [`glm::vec3(x, y, z)`](fn.vec3.html) will create a 3D vector.
* Using functions with the same name as their type in lower-case. For example [`glm::vec3(x, y, z)`](crate::vec3) will create a 3D vector.
* Using the `::new` constructor. For example [`Vec3::new(x, y, z)`](../nalgebra/base/type.OMatrix.html#method.new-27) will create a 3D vector.
* Using the functions prefixed by `make_` to build a vector a matrix from a slice. For example [`glm::make_vec3(&[x, y, z])`](fn.make_vec3.html) will create a 3D vector.
* Using the functions prefixed by `make_` to build a vector a matrix from a slice. For example [`glm::make_vec3(&[x, y, z])`](crate::make_vec3) will create a 3D vector.
Keep in mind that constructing a matrix using this type of functions require its components to be arranged in column-major order on the slice.
* Using a geometric construction function. For example [`glm::rotation(angle, axis)`](fn.rotation.html) will build a 4x4 homogeneous rotation matrix from an angle (in radians) and an axis.
* Using a geometric construction function. For example [`glm::rotation(angle, axis)`](crate::rotation) will build a 4x4 homogeneous rotation matrix from an angle (in radians) and an axis.
* Using swizzling and conversions as described in the next sections.
### Swizzling
Vector swizzling is a native feature of **nalgebra** itself. Therefore, you can use it with all
@ -75,9 +75,9 @@
It is often useful to convert one algebraic type to another. There are two main approaches for converting
between types in `nalgebra-glm`:
* Using function with the form `type1_to_type2` in order to convert an instance of `type1` into an instance of `type2`.
For example [`glm::mat3_to_mat4(m)`](fn.mat3_to_mat4.html) will convert the 3x3 matrix `m` to a 4x4 matrix by appending one column on the right
For example [`glm::mat3_to_mat4(m)`](crate::mat3_to_mat4) will convert the 3x3 matrix `m` to a 4x4 matrix by appending one column on the right
and one row on the left. Those now row and columns are filled with 0 except for the diagonal element which is set to 1.
* Using one of the [`convert`](fn.convert.html), [`try_convert`](fn.try_convert.html), or [`convert_unchecked`](fn.convert_unchecked.html) functions.
* Using one of the [`convert`](crate::convert), [`try_convert`](crate::try_convert), or [`convert_unchecked`](crate::convert_unchecked) functions.
These functions are directly re-exported from nalgebra and are extremely versatile:
1. The `convert` function can convert any type (especially geometric types from nalgebra like `Isometry3`) into another algebraic type which is equivalent but more general. For example,
`let sim: Similarity3<_> = na::convert(isometry)` will convert an `Isometry3` into a `Similarity3`.

View File

@ -1,7 +1,6 @@
use approx::AbsDiffEq;
use num::{Bounded, Signed};
use core::cmp::PartialOrd;
use na::Scalar;
use simba::scalar::{ClosedAdd, ClosedMul, ClosedSub, RealField};

View File

@ -1,5 +1,3 @@
use na;
use crate::aliases::TVec;
use crate::RealNumber;

View File

@ -16,8 +16,8 @@ use crate::traits::Number;
///
/// # See also:
///
/// * [`any`](fn.any.html)
/// * [`not`](fn.not.html)
/// * [`any()`]
/// * [`not()`]
pub fn all<const D: usize>(v: &TVec<bool, D>) -> bool {
v.iter().all(|x| *x)
}
@ -40,8 +40,8 @@ pub fn all<const D: usize>(v: &TVec<bool, D>) -> bool {
///
/// # See also:
///
/// * [`all`](fn.all.html)
/// * [`not`](fn.not.html)
/// * [`all()`]
/// * [`not()`]
pub fn any<const D: usize>(v: &TVec<bool, D>) -> bool {
v.iter().any(|x| *x)
}
@ -59,12 +59,12 @@ pub fn any<const D: usize>(v: &TVec<bool, D>) -> bool {
///
/// # See also:
///
/// * [`greater_than`](fn.greater_than.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than`](fn.less_than.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not`](fn.not.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`greater_than()`]
/// * [`greater_than_equal()`]
/// * [`less_than()`]
/// * [`less_than_equal()`]
/// * [`not()`]
/// * [`not_equal()`]
pub fn equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<bool, D> {
x.zip_map(y, |x, y| x == y)
}
@ -82,12 +82,12 @@ pub fn equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<
///
/// # See also:
///
/// * [`equal`](fn.equal.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than`](fn.less_than.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not`](fn.not.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`equal()`]
/// * [`greater_than_equal()`]
/// * [`less_than()`]
/// * [`less_than_equal()`]
/// * [`not()`]
/// * [`not_equal()`]
pub fn greater_than<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<bool, D> {
x.zip_map(y, |x, y| x > y)
}
@ -105,12 +105,12 @@ pub fn greater_than<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -
///
/// # See also:
///
/// * [`equal`](fn.equal.html)
/// * [`greater_than`](fn.greater_than.html)
/// * [`less_than`](fn.less_than.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not`](fn.not.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`equal()`]
/// * [`greater_than()`]
/// * [`less_than()`]
/// * [`less_than_equal()`]
/// * [`not()`]
/// * [`not_equal()`]
pub fn greater_than_equal<T: Number, const D: usize>(
x: &TVec<T, D>,
y: &TVec<T, D>,
@ -131,17 +131,17 @@ pub fn greater_than_equal<T: Number, const D: usize>(
///
/// # See also:
///
/// * [`equal`](fn.equal.html)
/// * [`greater_than`](fn.greater_than.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not`](fn.not.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`equal()`]
/// * [`greater_than()`]
/// * [`greater_than_equal()`]
/// * [`less_than_equal()`]
/// * [`not()`]
/// * [`not_equal()`]
pub fn less_than<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<bool, D> {
x.zip_map(y, |x, y| x < y)
}
/// Component-wise `>=` comparison.
/// Component-wise `<=` comparison.
///
/// # Examples:
///
@ -154,12 +154,12 @@ pub fn less_than<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> T
///
/// # See also:
///
/// * [`equal`](fn.equal.html)
/// * [`greater_than`](fn.greater_than.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than`](fn.less_than.html)
/// * [`not`](fn.not.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`equal()`]
/// * [`greater_than()`]
/// * [`greater_than_equal()`]
/// * [`less_than()`]
/// * [`not()`]
/// * [`not_equal()`]
pub fn less_than_equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<bool, D> {
x.zip_map(y, |x, y| x <= y)
}
@ -176,14 +176,14 @@ pub fn less_than_equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>
///
/// # See also:
///
/// * [`all`](fn.all.html)
/// * [`any`](fn.any.html)
/// * [`equal`](fn.equal.html)
/// * [`greater_than`](fn.greater_than.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than`](fn.less_than.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not_equal`](fn.not_equal.html)
/// * [`all()`]
/// * [`any()`]
/// * [`equal()`]
/// * [`greater_than()`]
/// * [`greater_than_equal()`]
/// * [`less_than()`]
/// * [`less_than_equal()`]
/// * [`not_equal()`]
pub fn not<const D: usize>(v: &TVec<bool, D>) -> TVec<bool, D> {
v.map(|x| !x)
}
@ -201,12 +201,12 @@ pub fn not<const D: usize>(v: &TVec<bool, D>) -> TVec<bool, D> {
///
/// # See also:
///
/// * [`equal`](fn.equal.html)
/// * [`greater_than`](fn.greater_than.html)
/// * [`greater_than_equal`](fn.greater_than_equal.html)
/// * [`less_than`](fn.less_than.html)
/// * [`less_than_equal`](fn.less_than_equal.html)
/// * [`not`](fn.not.html)
/// * [`equal()`]
/// * [`greater_than()`]
/// * [`greater_than_equal()`]
/// * [`less_than()`]
/// * [`less_than_equal()`]
/// * [`not()`]
pub fn not_equal<T: Number, const D: usize>(x: &TVec<T, D>, y: &TVec<T, D>) -> TVec<bool, D> {
x.zip_map(y, |x, y| x != y)
}

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra-lapack"
version = "0.21.0"
version = "0.24.0"
authors = [ "Sébastien Crozet <developer@crozet.re>", "Andrew Straw <strawman@astraw.com>" ]
description = "Matrix decompositions using nalgebra matrices and Lapack bindings."
@ -10,7 +10,7 @@ repository = "https://github.com/dimforge/nalgebra"
readme = "../README.md"
categories = [ "science", "mathematics" ]
keywords = [ "linear", "algebra", "matrix", "vector", "lapack" ]
license = "BSD-3-Clause"
license = "MIT"
edition = "2018"
[badges]
@ -29,18 +29,19 @@ accelerate = ["lapack-src/accelerate"]
intel-mkl = ["lapack-src/intel-mkl"]
[dependencies]
nalgebra = { version = "0.30", path = ".." }
nalgebra = { version = "0.32", path = ".." }
num-traits = "0.2"
num-complex = { version = "0.4", default-features = false }
simba = "0.7"
simba = "0.8"
serde = { version = "1.0", features = [ "derive" ], optional = true }
lapack = { version = "0.19", default-features = false }
lapack-src = { version = "0.8", default-features = false }
# clippy = "*"
[dev-dependencies]
nalgebra = { version = "0.30", features = [ "arbitrary", "rand" ], path = ".." }
nalgebra = { version = "0.32", features = [ "arbitrary", "rand" ], path = ".." }
proptest = { version = "1", default-features = false, features = ["std"] }
quickcheck = "1"
approx = "0.5"
rand = "0.8"

View File

@ -7,13 +7,12 @@ use num_complex::Complex;
use simba::scalar::RealField;
use crate::ComplexHelper;
use na::allocator::Allocator;
use na::dimension::{Const, Dim};
use na::{DefaultAllocator, Matrix, OMatrix, OVector, Scalar};
use na::{allocator::Allocator, DefaultAllocator, Matrix, OMatrix, OVector, Scalar};
use lapack;
/// Eigendecomposition of a real square matrix with real eigenvalues.
/// Eigendecomposition of a real square matrix with real or complex eigenvalues.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde-serialize",
@ -36,8 +35,10 @@ pub struct Eigen<T: Scalar, D: Dim>
where
DefaultAllocator: Allocator<T, D> + Allocator<T, D, D>,
{
/// The eigenvalues of the decomposed matrix.
pub eigenvalues: OVector<T, D>,
/// The real parts of eigenvalues of the decomposed matrix.
pub eigenvalues_re: OVector<T, D>,
/// The imaginary parts of the eigenvalues of the decomposed matrix.
pub eigenvalues_im: OVector<T, D>,
/// The (right) eigenvectors of the decomposed matrix.
pub eigenvectors: Option<OMatrix<T, D, D>>,
/// The left eigenvectors of the decomposed matrix.
@ -69,8 +70,8 @@ where
"Unable to compute the eigenvalue decomposition of a non-square matrix."
);
let ljob = if left_eigenvectors { b'V' } else { b'T' };
let rjob = if eigenvectors { b'V' } else { b'T' };
let ljob = if left_eigenvectors { b'V' } else { b'N' };
let rjob = if eigenvectors { b'V' } else { b'N' };
let (nrows, ncols) = m.shape_generic();
let n = nrows.value();
@ -104,213 +105,231 @@ where
lapack_check!(info);
let mut work = vec![T::zero(); lwork as usize];
match (left_eigenvectors, eigenvectors) {
(true, true) => {
// TODO: avoid the initializations?
let mut vl = Matrix::zeros_generic(nrows, ncols);
let mut vr = Matrix::zeros_generic(nrows, ncols);
T::xgeev(
ljob,
rjob,
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut vl.as_mut_slice(),
n as i32,
&mut vr.as_mut_slice(),
n as i32,
&mut work,
lwork,
&mut info,
);
lapack_check!(info);
if wi.iter().all(|e| e.is_zero()) {
return Some(Self {
eigenvalues: wr,
left_eigenvectors: Some(vl),
eigenvectors: Some(vr),
});
}
}
(true, false) => {
// TODO: avoid the initialization?
let mut vl = Matrix::zeros_generic(nrows, ncols);
T::xgeev(
ljob,
rjob,
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut vl.as_mut_slice(),
n as i32,
&mut placeholder2,
1 as i32,
&mut work,
lwork,
&mut info,
);
lapack_check!(info);
if wi.iter().all(|e| e.is_zero()) {
return Some(Self {
eigenvalues: wr,
left_eigenvectors: Some(vl),
eigenvectors: None,
});
}
}
(false, true) => {
// TODO: avoid the initialization?
let mut vr = Matrix::zeros_generic(nrows, ncols);
T::xgeev(
ljob,
rjob,
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut placeholder1,
1 as i32,
&mut vr.as_mut_slice(),
n as i32,
&mut work,
lwork,
&mut info,
);
lapack_check!(info);
if wi.iter().all(|e| e.is_zero()) {
return Some(Self {
eigenvalues: wr,
left_eigenvectors: None,
eigenvectors: Some(vr),
});
}
}
(false, false) => {
T::xgeev(
ljob,
rjob,
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut placeholder1,
1 as i32,
&mut placeholder2,
1 as i32,
&mut work,
lwork,
&mut info,
);
lapack_check!(info);
if wi.iter().all(|e| e.is_zero()) {
return Some(Self {
eigenvalues: wr,
left_eigenvectors: None,
eigenvectors: None,
});
}
}
}
let mut vl = if left_eigenvectors {
Some(Matrix::zeros_generic(nrows, ncols))
} else {
None
}
};
let mut vr = if eigenvectors {
Some(Matrix::zeros_generic(nrows, ncols))
} else {
None
};
/// The complex eigenvalues of the given matrix.
///
/// Panics if the eigenvalue computation does not converge.
pub fn complex_eigenvalues(mut m: OMatrix<T, D, D>) -> OVector<Complex<T>, D>
where
DefaultAllocator: Allocator<Complex<T>, D>,
{
assert!(
m.is_square(),
"Unable to compute the eigenvalue decomposition of a non-square matrix."
);
let nrows = m.shape_generic().0;
let n = nrows.value();
let lda = n as i32;
// TODO: avoid the initialization?
let mut wr = Matrix::zeros_generic(nrows, Const::<1>);
let mut wi = Matrix::zeros_generic(nrows, Const::<1>);
let mut info = 0;
let mut placeholder1 = [T::zero()];
let mut placeholder2 = [T::zero()];
let lwork = T::xgeev_work_size(
b'T',
b'T',
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut placeholder1,
n as i32,
&mut placeholder2,
n as i32,
&mut info,
);
lapack_panic!(info);
let mut work = vec![T::zero(); lwork as usize];
let vl_ref = vl
.as_mut()
.map(|m| m.as_mut_slice())
.unwrap_or(&mut placeholder1);
let vr_ref = vr
.as_mut()
.map(|m| m.as_mut_slice())
.unwrap_or(&mut placeholder2);
T::xgeev(
b'T',
b'T',
ljob,
rjob,
n as i32,
m.as_mut_slice(),
lda,
wr.as_mut_slice(),
wi.as_mut_slice(),
&mut placeholder1,
1 as i32,
&mut placeholder2,
1 as i32,
vl_ref,
if left_eigenvectors { n as i32 } else { 1 },
vr_ref,
if eigenvectors { n as i32 } else { 1 },
&mut work,
lwork,
&mut info,
);
lapack_panic!(info);
lapack_check!(info);
let mut res = Matrix::zeros_generic(nrows, Const::<1>);
for i in 0..res.len() {
res[i] = Complex::new(wr[i].clone(), wi[i].clone());
Some(Self {
eigenvalues_re: wr,
eigenvalues_im: wi,
left_eigenvectors: vl,
eigenvectors: vr,
})
}
res
/// Returns `true` if all the eigenvalues are real.
pub fn eigenvalues_are_real(&self) -> bool {
self.eigenvalues_im.iter().all(|e| e.is_zero())
}
/// The determinant of the decomposed matrix.
#[inline]
#[must_use]
pub fn determinant(&self) -> T {
let mut det = T::one();
for e in self.eigenvalues.iter() {
det *= e.clone();
pub fn determinant(&self) -> Complex<T> {
let mut det: Complex<T> = na::one();
for (re, im) in self.eigenvalues_re.iter().zip(self.eigenvalues_im.iter()) {
det *= Complex::new(re.clone(), im.clone());
}
det
}
/// Returns a tuple of vectors. The elements of the tuple are the real parts of the eigenvalues, left eigenvectors and right eigenvectors respectively.
pub fn get_real_elements(
&self,
) -> (
Vec<T>,
Option<Vec<OVector<T, D>>>,
Option<Vec<OVector<T, D>>>,
)
where
DefaultAllocator: Allocator<T, D>,
{
let (number_of_elements, _) = self.eigenvalues_re.shape_generic();
let number_of_elements_value = number_of_elements.value();
let mut eigenvalues = Vec::<T>::with_capacity(number_of_elements_value);
let mut eigenvectors = match self.eigenvectors.is_some() {
true => Some(Vec::<OVector<T, D>>::with_capacity(
number_of_elements_value,
)),
false => None,
};
let mut left_eigenvectors = match self.left_eigenvectors.is_some() {
true => Some(Vec::<OVector<T, D>>::with_capacity(
number_of_elements_value,
)),
false => None,
};
let mut c = 0;
while c < number_of_elements_value {
eigenvalues.push(self.eigenvalues_re[c].clone());
if eigenvectors.is_some() {
eigenvectors
.as_mut()
.unwrap()
.push(self.eigenvectors.as_ref().unwrap().column(c).into_owned());
}
if left_eigenvectors.is_some() {
left_eigenvectors.as_mut().unwrap().push(
self.left_eigenvectors
.as_ref()
.unwrap()
.column(c)
.into_owned(),
);
}
if self.eigenvalues_im[c] != T::zero() {
//skip next entry
c += 1;
}
c += 1;
}
(eigenvalues, left_eigenvectors, eigenvectors)
}
/// Returns a tuple of vectors. The elements of the tuple are the complex eigenvalues, complex left eigenvectors and complex right eigenvectors respectively.
/// The elements appear as conjugate pairs within each vector, with the positive of the pair always being first.
pub fn get_complex_elements(
&self,
) -> (
Option<Vec<Complex<T>>>,
Option<Vec<OVector<Complex<T>, D>>>,
Option<Vec<OVector<Complex<T>, D>>>,
)
where
DefaultAllocator: Allocator<Complex<T>, D>,
{
match self.eigenvalues_are_real() {
true => (None, None, None),
false => {
let (number_of_elements, _) = self.eigenvalues_re.shape_generic();
let number_of_elements_value = number_of_elements.value();
let number_of_complex_entries =
self.eigenvalues_im
.iter()
.fold(0, |acc, e| if !e.is_zero() { acc + 1 } else { acc });
let mut eigenvalues = Vec::<Complex<T>>::with_capacity(number_of_complex_entries);
let mut eigenvectors = match self.eigenvectors.is_some() {
true => Some(Vec::<OVector<Complex<T>, D>>::with_capacity(
number_of_complex_entries,
)),
false => None,
};
let mut left_eigenvectors = match self.left_eigenvectors.is_some() {
true => Some(Vec::<OVector<Complex<T>, D>>::with_capacity(
number_of_complex_entries,
)),
false => None,
};
let mut c = 0;
while c < number_of_elements_value {
if self.eigenvalues_im[c] != T::zero() {
//Complex conjugate pairs of eigenvalues appear consecutively with the eigenvalue having the positive imaginary part first.
eigenvalues.push(Complex::<T>::new(
self.eigenvalues_re[c].clone(),
self.eigenvalues_im[c].clone(),
));
eigenvalues.push(Complex::<T>::new(
self.eigenvalues_re[c + 1].clone(),
self.eigenvalues_im[c + 1].clone(),
));
if eigenvectors.is_some() {
let mut vec = OVector::<Complex<T>, D>::zeros_generic(
number_of_elements,
Const::<1>,
);
let mut vec_conj = OVector::<Complex<T>, D>::zeros_generic(
number_of_elements,
Const::<1>,
);
for r in 0..number_of_elements_value {
vec[r] = Complex::<T>::new(
self.eigenvectors.as_ref().unwrap()[(r, c)].clone(),
self.eigenvectors.as_ref().unwrap()[(r, c + 1)].clone(),
);
vec_conj[r] = Complex::<T>::new(
self.eigenvectors.as_ref().unwrap()[(r, c)].clone(),
self.eigenvectors.as_ref().unwrap()[(r, c + 1)].clone(),
);
}
eigenvectors.as_mut().unwrap().push(vec);
eigenvectors.as_mut().unwrap().push(vec_conj);
}
if left_eigenvectors.is_some() {
let mut vec = OVector::<Complex<T>, D>::zeros_generic(
number_of_elements,
Const::<1>,
);
let mut vec_conj = OVector::<Complex<T>, D>::zeros_generic(
number_of_elements,
Const::<1>,
);
for r in 0..number_of_elements_value {
vec[r] = Complex::<T>::new(
self.left_eigenvectors.as_ref().unwrap()[(r, c)].clone(),
self.left_eigenvectors.as_ref().unwrap()[(r, c + 1)].clone(),
);
vec_conj[r] = Complex::<T>::new(
self.left_eigenvectors.as_ref().unwrap()[(r, c)].clone(),
self.left_eigenvectors.as_ref().unwrap()[(r, c + 1)].clone(),
);
}
left_eigenvectors.as_mut().unwrap().push(vec);
left_eigenvectors.as_mut().unwrap().push(vec_conj);
}
//skip next entry
c += 1;
}
c += 1;
}
(Some(eigenvalues), left_eigenvectors, eigenvectors)
}
}
}
}
/*

View File

@ -0,0 +1,350 @@
#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};
use num::Zero;
use num_complex::Complex;
use simba::scalar::RealField;
use crate::ComplexHelper;
use na::allocator::Allocator;
use na::dimension::{Const, Dim};
use na::{DefaultAllocator, Matrix, OMatrix, OVector, Scalar};
use lapack;
/// Generalized eigenvalues and generalized eigenvectors (left and right) of a pair of N*N real square matrices.
///
/// Each generalized eigenvalue (lambda) satisfies determinant(A - lambda*B) = 0
///
/// The right eigenvector v(j) corresponding to the eigenvalue lambda(j)
/// of (A,B) satisfies
///
/// A * v(j) = lambda(j) * B * v(j).
///
/// The left eigenvector u(j) corresponding to the eigenvalue lambda(j)
/// of (A,B) satisfies
///
/// u(j)**H * A = lambda(j) * u(j)**H * B .
/// where u(j)**H is the conjugate-transpose of u(j).
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(serialize = "DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OVector<T, D>: Serialize,
OMatrix<T, D, D>: Serialize")
)
)]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(deserialize = "DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OVector<T, D>: Deserialize<'de>,
OMatrix<T, D, D>: Deserialize<'de>")
)
)]
#[derive(Clone, Debug)]
pub struct GeneralizedEigen<T: Scalar, D: Dim>
where
DefaultAllocator: Allocator<T, D> + Allocator<T, D, D>,
{
alphar: OVector<T, D>,
alphai: OVector<T, D>,
beta: OVector<T, D>,
vsl: OMatrix<T, D, D>,
vsr: OMatrix<T, D, D>,
}
impl<T: Scalar + Copy, D: Dim> Copy for GeneralizedEigen<T, D>
where
DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OMatrix<T, D, D>: Copy,
OVector<T, D>: Copy,
{
}
impl<T: GeneralizedEigenScalar + RealField + Copy, D: Dim> GeneralizedEigen<T, D>
where
DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
{
/// Attempts to compute the generalized eigenvalues, and left and right associated eigenvectors
/// via the raw returns from LAPACK's dggev and sggev routines
///
/// Panics if the method did not converge.
pub fn new(a: OMatrix<T, D, D>, b: OMatrix<T, D, D>) -> Self {
Self::try_new(a, b).expect("Calculation of generalized eigenvalues failed.")
}
/// Attempts to compute the generalized eigenvalues (and eigenvectors) via the raw returns from LAPACK's
/// dggev and sggev routines
///
/// Returns `None` if the method did not converge.
pub fn try_new(mut a: OMatrix<T, D, D>, mut b: OMatrix<T, D, D>) -> Option<Self> {
assert!(
a.is_square() && b.is_square(),
"Unable to compute the generalized eigenvalues of non-square matrices."
);
assert!(
a.shape_generic() == b.shape_generic(),
"Unable to compute the generalized eigenvalues of two square matrices of different dimensions."
);
let (nrows, ncols) = a.shape_generic();
let n = nrows.value();
let mut info = 0;
let mut alphar = Matrix::zeros_generic(nrows, Const::<1>);
let mut alphai = Matrix::zeros_generic(nrows, Const::<1>);
let mut beta = Matrix::zeros_generic(nrows, Const::<1>);
let mut vsl = Matrix::zeros_generic(nrows, ncols);
let mut vsr = Matrix::zeros_generic(nrows, ncols);
let lwork = T::xggev_work_size(
b'V',
b'V',
n as i32,
a.as_mut_slice(),
n as i32,
b.as_mut_slice(),
n as i32,
alphar.as_mut_slice(),
alphai.as_mut_slice(),
beta.as_mut_slice(),
vsl.as_mut_slice(),
n as i32,
vsr.as_mut_slice(),
n as i32,
&mut info,
);
lapack_check!(info);
let mut work = vec![T::zero(); lwork as usize];
T::xggev(
b'V',
b'V',
n as i32,
a.as_mut_slice(),
n as i32,
b.as_mut_slice(),
n as i32,
alphar.as_mut_slice(),
alphai.as_mut_slice(),
beta.as_mut_slice(),
vsl.as_mut_slice(),
n as i32,
vsr.as_mut_slice(),
n as i32,
&mut work,
lwork,
&mut info,
);
lapack_check!(info);
Some(GeneralizedEigen {
alphar,
alphai,
beta,
vsl,
vsr,
})
}
/// Calculates the generalized eigenvectors (left and right) associated with the generalized eigenvalues
///
/// Outputs two matrices.
/// The first output matrix contains the left eigenvectors of the generalized eigenvalues
/// as columns.
/// The second matrix contains the right eigenvectors of the generalized eigenvalues
/// as columns.
pub fn eigenvectors(&self) -> (OMatrix<Complex<T>, D, D>, OMatrix<Complex<T>, D, D>)
where
DefaultAllocator:
Allocator<Complex<T>, D, D> + Allocator<Complex<T>, D> + Allocator<(Complex<T>, T), D>,
{
/*
How the eigenvectors are built up:
Since the input entries are all real, the generalized eigenvalues if complex come in pairs
as a consequence of the [complex conjugate root thorem](https://en.wikipedia.org/wiki/Complex_conjugate_root_theorem)
The Lapack routine output reflects this by expecting the user to unpack the real and complex eigenvalues associated
eigenvectors from the real matrix output via the following procedure
(Note: VL stands for the lapack real matrix output containing the left eigenvectors as columns,
VR stands for the lapack real matrix output containing the right eigenvectors as columns)
If the j-th and (j+1)-th eigenvalues form a complex conjugate pair,
then
u(j) = VL(:,j)+i*VL(:,j+1)
u(j+1) = VL(:,j)-i*VL(:,j+1)
and
u(j) = VR(:,j)+i*VR(:,j+1)
v(j+1) = VR(:,j)-i*VR(:,j+1).
*/
let n = self.vsl.shape().0;
let mut l = self.vsl.map(|x| Complex::new(x, T::RealField::zero()));
let mut r = self.vsr.map(|x| Complex::new(x, T::RealField::zero()));
let eigenvalues = self.raw_eigenvalues();
let mut c = 0;
while c < n {
if eigenvalues[c].0.im.abs() != T::RealField::zero() && c + 1 < n {
// taking care of the left eigenvector matrix
l.column_mut(c).zip_apply(&self.vsl.column(c + 1), |r, i| {
*r = Complex::new(r.re.clone(), i.clone());
});
l.column_mut(c + 1).zip_apply(&self.vsl.column(c), |i, r| {
*i = Complex::new(r.clone(), -i.re.clone());
});
// taking care of the right eigenvector matrix
r.column_mut(c).zip_apply(&self.vsr.column(c + 1), |r, i| {
*r = Complex::new(r.re.clone(), i.clone());
});
r.column_mut(c + 1).zip_apply(&self.vsr.column(c), |i, r| {
*i = Complex::new(r.clone(), -i.re.clone());
});
c += 2;
} else {
c += 1;
}
}
(l, r)
}
/// Outputs the unprocessed (almost) version of generalized eigenvalues ((alphar, alphai), beta)
/// straight from LAPACK
#[must_use]
pub fn raw_eigenvalues(&self) -> OVector<(Complex<T>, T), D>
where
DefaultAllocator: Allocator<(Complex<T>, T), D>,
{
let mut out = Matrix::from_element_generic(
self.vsl.shape_generic().0,
Const::<1>,
(Complex::zero(), T::RealField::zero()),
);
for i in 0..out.len() {
out[i] = (Complex::new(self.alphar[i], self.alphai[i]), self.beta[i])
}
out
}
}
/*
*
* Lapack functions dispatch.
*
*/
/// Trait implemented by scalars for which Lapack implements the RealField GeneralizedEigen decomposition.
pub trait GeneralizedEigenScalar: Scalar {
#[allow(missing_docs)]
fn xggev(
jobvsl: u8,
jobvsr: u8,
n: i32,
a: &mut [Self],
lda: i32,
b: &mut [Self],
ldb: i32,
alphar: &mut [Self],
alphai: &mut [Self],
beta: &mut [Self],
vsl: &mut [Self],
ldvsl: i32,
vsr: &mut [Self],
ldvsr: i32,
work: &mut [Self],
lwork: i32,
info: &mut i32,
);
#[allow(missing_docs)]
fn xggev_work_size(
jobvsl: u8,
jobvsr: u8,
n: i32,
a: &mut [Self],
lda: i32,
b: &mut [Self],
ldb: i32,
alphar: &mut [Self],
alphai: &mut [Self],
beta: &mut [Self],
vsl: &mut [Self],
ldvsl: i32,
vsr: &mut [Self],
ldvsr: i32,
info: &mut i32,
) -> i32;
}
macro_rules! generalized_eigen_scalar_impl (
($N: ty, $xggev: path) => (
impl GeneralizedEigenScalar for $N {
#[inline]
fn xggev(jobvsl: u8,
jobvsr: u8,
n: i32,
a: &mut [$N],
lda: i32,
b: &mut [$N],
ldb: i32,
alphar: &mut [$N],
alphai: &mut [$N],
beta : &mut [$N],
vsl: &mut [$N],
ldvsl: i32,
vsr: &mut [$N],
ldvsr: i32,
work: &mut [$N],
lwork: i32,
info: &mut i32) {
unsafe { $xggev(jobvsl, jobvsr, n, a, lda, b, ldb, alphar, alphai, beta, vsl, ldvsl, vsr, ldvsr, work, lwork, info); }
}
#[inline]
fn xggev_work_size(jobvsl: u8,
jobvsr: u8,
n: i32,
a: &mut [$N],
lda: i32,
b: &mut [$N],
ldb: i32,
alphar: &mut [$N],
alphai: &mut [$N],
beta : &mut [$N],
vsl: &mut [$N],
ldvsl: i32,
vsr: &mut [$N],
ldvsr: i32,
info: &mut i32)
-> i32 {
let mut work = [ Zero::zero() ];
let lwork = -1 as i32;
unsafe { $xggev(jobvsl, jobvsr, n, a, lda, b, ldb, alphar, alphai, beta, vsl, ldvsl, vsr, ldvsr, &mut work, lwork, info); }
ComplexHelper::real_part(work[0]) as i32
}
}
)
);
generalized_eigen_scalar_impl!(f32, lapack::sggev);
generalized_eigen_scalar_impl!(f64, lapack::dggev);

View File

@ -83,9 +83,11 @@ mod lapack_check;
mod cholesky;
mod eigen;
mod generalized_eigenvalues;
mod hessenberg;
mod lu;
mod qr;
mod qz;
mod schur;
mod svd;
mod symmetric_eigen;
@ -94,9 +96,11 @@ use num_complex::Complex;
pub use self::cholesky::{Cholesky, CholeskyScalar};
pub use self::eigen::Eigen;
pub use self::generalized_eigenvalues::GeneralizedEigen;
pub use self::hessenberg::Hessenberg;
pub use self::lu::{LUScalar, LU};
pub use self::qr::QR;
pub use self::qz::QZ;
pub use self::schur::Schur;
pub use self::svd::SVD;
pub use self::symmetric_eigen::SymmetricEigen;

View File

@ -126,7 +126,7 @@ where
let mut q = self
.qr
.generic_slice((0, 0), (nrows, min_nrows_ncols))
.generic_view((0, 0), (nrows, min_nrows_ncols))
.into_owned();
let mut info = 0;

321
nalgebra-lapack/src/qz.rs Normal file
View File

@ -0,0 +1,321 @@
#[cfg(feature = "serde-serialize")]
use serde::{Deserialize, Serialize};
use num::Zero;
use num_complex::Complex;
use simba::scalar::RealField;
use crate::ComplexHelper;
use na::allocator::Allocator;
use na::dimension::{Const, Dim};
use na::{DefaultAllocator, Matrix, OMatrix, OVector, Scalar};
use lapack;
/// QZ decomposition of a pair of N*N square matrices.
///
/// Retrieves the left and right matrices of Schur Vectors (VSL and VSR)
/// the upper-quasitriangular matrix `S` and upper triangular matrix `T` such that the
/// decomposed input matrix `a` equals `VSL * S * VSL.transpose()` and
/// decomposed input matrix `b` equals `VSL * T * VSL.transpose()`.
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(serialize = "DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OVector<T, D>: Serialize,
OMatrix<T, D, D>: Serialize")
)
)]
#[cfg_attr(
feature = "serde-serialize",
serde(
bound(deserialize = "DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OVector<T, D>: Deserialize<'de>,
OMatrix<T, D, D>: Deserialize<'de>")
)
)]
#[derive(Clone, Debug)]
pub struct QZ<T: Scalar, D: Dim>
where
DefaultAllocator: Allocator<T, D> + Allocator<T, D, D>,
{
alphar: OVector<T, D>,
alphai: OVector<T, D>,
beta: OVector<T, D>,
vsl: OMatrix<T, D, D>,
s: OMatrix<T, D, D>,
vsr: OMatrix<T, D, D>,
t: OMatrix<T, D, D>,
}
impl<T: Scalar + Copy, D: Dim> Copy for QZ<T, D>
where
DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
OMatrix<T, D, D>: Copy,
OVector<T, D>: Copy,
{
}
impl<T: QZScalar + RealField, D: Dim> QZ<T, D>
where
DefaultAllocator: Allocator<T, D, D> + Allocator<T, D>,
{
/// Attempts to compute the QZ decomposition of input real square matrices `a` and `b`.
///
/// i.e retrieves the left and right matrices of Schur Vectors (VSL and VSR)
/// the upper-quasitriangular matrix `S` and upper triangular matrix `T` such that the
/// decomposed matrix `a` equals `VSL * S * VSL.transpose()` and
/// decomposed matrix `b` equals `VSL * T * VSL.transpose()`.
///
/// Panics if the method did not converge.
pub fn new(a: OMatrix<T, D, D>, b: OMatrix<T, D, D>) -> Self {
Self::try_new(a, b).expect("QZ decomposition: convergence failed.")
}
/// Computes the decomposition of input matrices `a` and `b` into a pair of matrices of Schur vectors
/// , a quasi-upper triangular matrix and an upper-triangular matrix .
///
/// Returns `None` if the method did not converge.
pub fn try_new(mut a: OMatrix<T, D, D>, mut b: OMatrix<T, D, D>) -> Option<Self> {
assert!(
a.is_square() && b.is_square(),
"Unable to compute the qz decomposition of non-square matrices."
);
assert!(
a.shape_generic() == b.shape_generic(),
"Unable to compute the qz decomposition of two square matrices of different dimensions."
);
let (nrows, ncols) = a.shape_generic();
let n = nrows.value();
let mut info = 0;
let mut alphar = Matrix::zeros_generic(nrows, Const::<1>);
let mut alphai = Matrix::zeros_generic(nrows, Const::<1>);
let mut beta = Matrix::zeros_generic(nrows, Const::<1>);
let mut vsl = Matrix::zeros_generic(nrows, ncols);
let mut vsr = Matrix::zeros_generic(nrows, ncols);
// Placeholders:
let mut bwork = [0i32];
let mut unused = 0;
let lwork = T::xgges_work_size(
b'V',
b'V',
b'N',
n as i32,
a.as_mut_slice(),
n as i32,
b.as_mut_slice(),
n as i32,
&mut unused,
alphar.as_mut_slice(),
alphai.as_mut_slice(),
beta.as_mut_slice(),
vsl.as_mut_slice(),
n as i32,
vsr.as_mut_slice(),
n as i32,
&mut bwork,
&mut info,
);
lapack_check!(info);
let mut work = vec![T::zero(); lwork as usize];
T::xgges(
b'V',
b'V',
b'N',
n as i32,
a.as_mut_slice(),
n as i32,
b.as_mut_slice(),
n as i32,
&mut unused,
alphar.as_mut_slice(),
alphai.as_mut_slice(),
beta.as_mut_slice(),
vsl.as_mut_slice(),
n as i32,
vsr.as_mut_slice(),
n as i32,
&mut work,
lwork,
&mut bwork,
&mut info,
);
lapack_check!(info);
Some(QZ {
alphar,
alphai,
beta,
vsl,
s: a,
vsr,
t: b,
})
}
/// Retrieves the left and right matrices of Schur Vectors (VSL and VSR)
/// the upper-quasitriangular matrix `S` and upper triangular matrix `T` such that the
/// decomposed input matrix `a` equals `VSL * S * VSL.transpose()` and
/// decomposed input matrix `b` equals `VSL * T * VSL.transpose()`.
pub fn unpack(
self,
) -> (
OMatrix<T, D, D>,
OMatrix<T, D, D>,
OMatrix<T, D, D>,
OMatrix<T, D, D>,
) {
(self.vsl, self.s, self.t, self.vsr)
}
/// outputs the unprocessed (almost) version of generalized eigenvalues ((alphar, alpai), beta)
/// straight from LAPACK
#[must_use]
pub fn raw_eigenvalues(&self) -> OVector<(Complex<T>, T), D>
where
DefaultAllocator: Allocator<(Complex<T>, T), D>,
{
let mut out = Matrix::from_element_generic(
self.vsl.shape_generic().0,
Const::<1>,
(Complex::zero(), T::RealField::zero()),
);
for i in 0..out.len() {
out[i] = (
Complex::new(self.alphar[i].clone(), self.alphai[i].clone()),
self.beta[i].clone(),
)
}
out
}
}
/*
*
* Lapack functions dispatch.
*
*/
/// Trait implemented by scalars for which Lapack implements the RealField QZ decomposition.
pub trait QZScalar: Scalar {
#[allow(missing_docs)]
fn xgges(
jobvsl: u8,
jobvsr: u8,
sort: u8,
// select: ???
n: i32,
a: &mut [Self],
lda: i32,
b: &mut [Self],
ldb: i32,
sdim: &mut i32,
alphar: &mut [Self],
alphai: &mut [Self],
beta: &mut [Self],
vsl: &mut [Self],
ldvsl: i32,
vsr: &mut [Self],
ldvsr: i32,
work: &mut [Self],
lwork: i32,
bwork: &mut [i32],
info: &mut i32,
);
#[allow(missing_docs)]
fn xgges_work_size(
jobvsl: u8,
jobvsr: u8,
sort: u8,
// select: ???
n: i32,
a: &mut [Self],
lda: i32,
b: &mut [Self],
ldb: i32,
sdim: &mut i32,
alphar: &mut [Self],
alphai: &mut [Self],
beta: &mut [Self],
vsl: &mut [Self],
ldvsl: i32,
vsr: &mut [Self],
ldvsr: i32,
bwork: &mut [i32],
info: &mut i32,
) -> i32;
}
macro_rules! qz_scalar_impl (
($N: ty, $xgges: path) => (
impl QZScalar for $N {
#[inline]
fn xgges(jobvsl: u8,
jobvsr: u8,
sort: u8,
// select: ???
n: i32,
a: &mut [$N],
lda: i32,
b: &mut [$N],
ldb: i32,
sdim: &mut i32,
alphar: &mut [$N],
alphai: &mut [$N],
beta : &mut [$N],
vsl: &mut [$N],
ldvsl: i32,
vsr: &mut [$N],
ldvsr: i32,
work: &mut [$N],
lwork: i32,
bwork: &mut [i32],
info: &mut i32) {
unsafe { $xgges(jobvsl, jobvsr, sort, None, n, a, lda, b, ldb, sdim, alphar, alphai, beta, vsl, ldvsl, vsr, ldvsr, work, lwork, bwork, info); }
}
#[inline]
fn xgges_work_size(jobvsl: u8,
jobvsr: u8,
sort: u8,
// select: ???
n: i32,
a: &mut [$N],
lda: i32,
b: &mut [$N],
ldb: i32,
sdim: &mut i32,
alphar: &mut [$N],
alphai: &mut [$N],
beta : &mut [$N],
vsl: &mut [$N],
ldvsl: i32,
vsr: &mut [$N],
ldvsr: i32,
bwork: &mut [i32],
info: &mut i32)
-> i32 {
let mut work = [ Zero::zero() ];
let lwork = -1 as i32;
unsafe { $xgges(jobvsl, jobvsr, sort, None, n, a, lda, b, ldb, sdim, alphar, alphai, beta, vsl, ldvsl, vsr, ldvsr, &mut work, lwork, bwork, info); }
ComplexHelper::real_part(work[0]) as i32
}
}
)
);
qz_scalar_impl!(f32, lapack::sgges);
qz_scalar_impl!(f64, lapack::dgges);

View File

@ -157,7 +157,7 @@ macro_rules! svd_impl(
let mut res: OMatrix<_, R, C> = Matrix::zeros_generic(nrows, ncols);
{
let mut sres = res.generic_slice_mut((0, 0), (min_nrows_ncols, ncols));
let mut sres = res.generic_view_mut((0, 0), (min_nrows_ncols, ncols));
sres.copy_from(&self.vt.rows_generic(0, min_nrows_ncols));
for i in 0 .. min_nrows_ncols.value() {
@ -183,7 +183,7 @@ macro_rules! svd_impl(
let mut res: OMatrix<_, C, R> = Matrix::zeros_generic(ncols, nrows);
{
let mut sres = res.generic_slice_mut((0, 0), (min_nrows_ncols, nrows));
let mut sres = res.generic_view_mut((0, 0), (min_nrows_ncols, nrows));
self.u.columns_generic(0, min_nrows_ncols).transpose_to(&mut sres);
for i in 0 .. min_nrows_ncols.value() {

View File

@ -58,8 +58,8 @@ proptest! {
let sol1 = chol.solve(&b1).unwrap();
let sol2 = chol.solve(&b2).unwrap();
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-4));
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-4));
}
}
@ -84,7 +84,7 @@ proptest! {
let id1 = &m * &m1;
let id2 = &m1 * &m;
prop_assert!(id1.is_identity(1.0e-5) && id2.is_identity(1.0e-5))
prop_assert!(id1.is_identity(1.0e-4) && id2.is_identity(1.0e-4))
}
}
}

View File

@ -0,0 +1,47 @@
use na::Matrix3;
use nalgebra_lapack::Eigen;
use num_complex::Complex;
#[test]
fn complex_eigen() {
let m = Matrix3::<f64>::new(
4.0 / 5.0,
-3.0 / 5.0,
0.0,
3.0 / 5.0,
4.0 / 5.0,
0.0,
1.0,
2.0,
2.0,
);
let eigen = Eigen::new(m, true, true).expect("Eigen Creation Failed!");
let (some_eigenvalues, some_left_vec, some_right_vec) = eigen.get_complex_elements();
let eigenvalues = some_eigenvalues.expect("Eigenvalues Failed");
let _left_eigenvectors = some_left_vec.expect("Left Eigenvectors Failed");
let eigenvectors = some_right_vec.expect("Right Eigenvectors Failed");
assert_relative_eq!(
eigenvalues[0].re,
Complex::<f64>::new(4.0 / 5.0, 3.0 / 5.0).re
);
assert_relative_eq!(
eigenvalues[0].im,
Complex::<f64>::new(4.0 / 5.0, 3.0 / 5.0).im
);
assert_relative_eq!(
eigenvalues[1].re,
Complex::<f64>::new(4.0 / 5.0, -3.0 / 5.0).re
);
assert_relative_eq!(
eigenvalues[1].im,
Complex::<f64>::new(4.0 / 5.0, -3.0 / 5.0).im
);
assert_relative_eq!(eigenvectors[0][0].re, -12.0 / 32.7871926215100059134410999);
assert_relative_eq!(eigenvectors[0][0].im, -9.0 / 32.7871926215100059134410999);
assert_relative_eq!(eigenvectors[0][1].re, -9.0 / 32.7871926215100059134410999);
assert_relative_eq!(eigenvectors[0][1].im, 12.0 / 32.7871926215100059134410999);
assert_relative_eq!(eigenvectors[0][2].re, 25.0 / 32.7871926215100059134410999);
assert_relative_eq!(eigenvectors[0][2].im, 0.0);
}

View File

@ -0,0 +1,72 @@
use na::dimension::Const;
use na::{DMatrix, OMatrix};
use nl::GeneralizedEigen;
use num_complex::Complex;
use simba::scalar::ComplexField;
use crate::proptest::*;
use proptest::{prop_assert, prop_compose, proptest};
prop_compose! {
fn f64_dynamic_dim_squares()
(n in PROPTEST_MATRIX_DIM)
(a in matrix(PROPTEST_F64,n,n), b in matrix(PROPTEST_F64,n,n)) -> (DMatrix<f64>, DMatrix<f64>){
(a,b)
}}
proptest! {
#[test]
fn ge((a,b) in f64_dynamic_dim_squares()){
let a_c = a.clone().map(|x| Complex::new(x, 0.0));
let b_c = b.clone().map(|x| Complex::new(x, 0.0));
let n = a.shape_generic().0;
let ge = GeneralizedEigen::new(a.clone(), b.clone());
let (vsl,vsr) = ge.clone().eigenvectors();
for (i,(alpha,beta)) in ge.raw_eigenvalues().iter().enumerate() {
let l_a = a_c.clone() * Complex::new(*beta, 0.0);
let l_b = b_c.clone() * *alpha;
prop_assert!(
relative_eq!(
((&l_a - &l_b)*vsr.column(i)).map(|x| x.modulus()),
OMatrix::zeros_generic(n, Const::<1>),
epsilon = 1.0e-5));
prop_assert!(
relative_eq!(
(vsl.column(i).adjoint()*(&l_a - &l_b)).map(|x| x.modulus()),
OMatrix::zeros_generic(Const::<1>, n),
epsilon = 1.0e-5))
};
}
#[test]
fn ge_static(a in matrix4(), b in matrix4()) {
let ge = GeneralizedEigen::new(a.clone(), b.clone());
let a_c =a.clone().map(|x| Complex::new(x, 0.0));
let b_c = b.clone().map(|x| Complex::new(x, 0.0));
let (vsl,vsr) = ge.eigenvectors();
let eigenvalues = ge.raw_eigenvalues();
for (i,(alpha,beta)) in eigenvalues.iter().enumerate() {
let l_a = a_c.clone() * Complex::new(*beta, 0.0);
let l_b = b_c.clone() * *alpha;
prop_assert!(
relative_eq!(
((&l_a - &l_b)*vsr.column(i)).map(|x| x.modulus()),
OMatrix::zeros_generic(Const::<4>, Const::<1>),
epsilon = 1.0e-5));
prop_assert!(
relative_eq!((vsl.column(i).adjoint()*(&l_a - &l_b)).map(|x| x.modulus()),
OMatrix::zeros_generic(Const::<1>, Const::<4>),
epsilon = 1.0e-5))
}
}
}

View File

@ -51,10 +51,10 @@ proptest! {
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
prop_assert!(relative_eq!(&m * sol1, b1, epsilon = 1.0e-7));
prop_assert!(relative_eq!(&m * sol2, b2, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7));
prop_assert!(relative_eq!(&m * sol1, b1, epsilon = 1.0e-5));
prop_assert!(relative_eq!(&m * sol2, b2, epsilon = 1.0e-5));
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-5));
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-5));
}
#[test]
@ -68,10 +68,10 @@ proptest! {
let tr_sol1 = lup.solve_transpose(&b1).unwrap();
let tr_sol2 = lup.solve_transpose(&b2).unwrap();
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-7));
prop_assert!(relative_eq!(m * sol1, b1, epsilon = 1.0e-5));
prop_assert!(relative_eq!(m * sol2, b2, epsilon = 1.0e-5));
prop_assert!(relative_eq!(m.transpose() * tr_sol1, b1, epsilon = 1.0e-5));
prop_assert!(relative_eq!(m.transpose() * tr_sol2, b2, epsilon = 1.0e-5));
}
#[test]

View File

@ -1,6 +1,9 @@
mod cholesky;
mod complex_eigen;
mod generalized_eigenvalues;
mod lu;
mod qr;
mod qz;
mod real_eigensystem;
mod schur;
mod svd;

View File

@ -0,0 +1,34 @@
use na::DMatrix;
use nl::QZ;
use crate::proptest::*;
use proptest::{prop_assert, prop_compose, proptest};
prop_compose! {
fn f64_dynamic_dim_squares()
(n in PROPTEST_MATRIX_DIM)
(a in matrix(PROPTEST_F64,n,n), b in matrix(PROPTEST_F64,n,n)) -> (DMatrix<f64>, DMatrix<f64>){
(a,b)
}}
proptest! {
#[test]
fn qz((a,b) in f64_dynamic_dim_squares()) {
let qz = QZ::new(a.clone(), b.clone());
let (vsl,s,t,vsr) = qz.clone().unpack();
prop_assert!(relative_eq!(&vsl * s * vsr.transpose(), a, epsilon = 1.0e-7));
prop_assert!(relative_eq!(vsl * t * vsr.transpose(), b, epsilon = 1.0e-7));
}
#[test]
fn qz_static(a in matrix4(), b in matrix4()) {
let qz = QZ::new(a.clone(), b.clone());
let (vsl,s,t,vsr) = qz.unpack();
prop_assert!(relative_eq!(&vsl * s * vsr.transpose(), a, epsilon = 1.0e-7));
prop_assert!(relative_eq!(vsl * t * vsr.transpose(), b, epsilon = 1.0e-7));
}
}

View File

@ -13,30 +13,36 @@ proptest! {
let m = DMatrix::<f64>::new_random(n, n);
if let Some(eig) = Eigen::new(m.clone(), true, true) {
let eigvals = DMatrix::from_diagonal(&eig.eigenvalues);
// TODO: test the complex case too.
if eig.eigenvalues_are_real() {
let eigvals = DMatrix::from_diagonal(&eig.eigenvalues_re);
let transformed_eigvectors = &m * eig.eigenvectors.as_ref().unwrap();
let scaled_eigvectors = eig.eigenvectors.as_ref().unwrap() * &eigvals;
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.as_ref().unwrap();
let scaled_left_eigvectors = eig.left_eigenvectors.as_ref().unwrap() * &eigvals;
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7));
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7));
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-5));
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-5));
}
}
}
#[test]
fn eigensystem_static(m in matrix4()) {
if let Some(eig) = Eigen::new(m, true, true) {
let eigvals = Matrix4::from_diagonal(&eig.eigenvalues);
// TODO: test the complex case too.
if eig.eigenvalues_are_real() {
let eigvals = Matrix4::from_diagonal(&eig.eigenvalues_re);
let transformed_eigvectors = m * eig.eigenvectors.unwrap();
let scaled_eigvectors = eig.eigenvectors.unwrap() * eigvals;
let transformed_left_eigvectors = m.transpose() * eig.left_eigenvectors.unwrap();
let scaled_left_eigvectors = eig.left_eigenvectors.unwrap() * eigvals;
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-7));
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-7));
prop_assert!(relative_eq!(transformed_eigvectors, scaled_eigvectors, epsilon = 1.0e-5));
prop_assert!(relative_eq!(transformed_left_eigvectors, scaled_left_eigvectors, epsilon = 1.0e-5));
}
}
}
}

View File

@ -11,14 +11,17 @@ proptest! {
let n = cmp::max(1, cmp::min(n, 10));
let m = DMatrix::<f64>::new_random(n, n);
let (vecs, vals) = Schur::new(m.clone()).unpack();
prop_assert!(relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7))
if let Some(schur) = Schur::try_new(m.clone()) {
let (vecs, vals) = schur.unpack();
prop_assert!(relative_eq!(&vecs * vals * vecs.transpose(), m, epsilon = 1.0e-5))
}
}
#[test]
fn schur_static(m in matrix4()) {
let (vecs, vals) = Schur::new(m.clone()).unpack();
prop_assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-7))
if let Some(schur) = Schur::try_new(m.clone()) {
let (vecs, vals) = schur.unpack();
prop_assert!(relative_eq!(vecs * vals * vecs.transpose(), m, epsilon = 1.0e-5))
}
}
}

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra-macros"
version = "0.1.0"
version = "0.2.1"
authors = [ "Andreas Longva", "Sébastien Crozet <developer@crozet.re>" ]
edition = "2018"
description = "Procedural macros for nalgebra"
@ -21,5 +21,5 @@ quote = "1.0"
proc-macro2 = "1.0"
[dev-dependencies]
nalgebra = { version = "0.30.0", path = ".." }
nalgebra = { version = "0.32.0", path = ".." }
trybuild = "1.0.42"

1
nalgebra-macros/LICENSE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE

View File

@ -191,8 +191,8 @@ pub fn dmatrix(stream: TokenStream) -> TokenStream {
let output = quote! {
nalgebra::DMatrix::<_>
::from_vec_storage(nalgebra::VecStorage::new(
nalgebra::Dynamic::new(#row_dim),
nalgebra::Dynamic::new(#col_dim),
nalgebra::Dyn(#row_dim),
nalgebra::Dyn(#col_dim),
vec!#array_tokens))
};
@ -223,7 +223,7 @@ impl Parse for Vector {
elements: Vec::new(),
})
} else {
let elements = MatrixRowSyntax::parse_separated_nonempty(input)?
let elements = MatrixRowSyntax::parse_terminated(input)?
.into_iter()
.collect();
Ok(Self { elements })
@ -285,7 +285,7 @@ pub fn dvector(stream: TokenStream) -> TokenStream {
let output = quote! {
nalgebra::DVector::<_>
::from_vec_storage(nalgebra::VecStorage::new(
nalgebra::Dynamic::new(#len),
nalgebra::Dyn(#len),
nalgebra::Const::<1>,
vec!#array_tokens))
};

View File

@ -94,6 +94,12 @@ fn dmatrix_small_dims_exhaustive() {
DMatrix::from_row_slice(4, 4, &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]));
}
#[test]
fn matrix_trailing_semi() {
matrix![1, 2;];
dmatrix![1, 2;];
}
// Skip rustfmt because it just makes the test bloated without making it more readable
#[rustfmt::skip]
#[test]
@ -151,6 +157,13 @@ fn dvector_small_dims_exhaustive() {
assert_eq_and_type!(dvector![1, 2, 3, 4, 5, 6], DVector::from_column_slice(&[1, 2, 3, 4, 5, 6]));
}
#[test]
fn vector_trailing_comma() {
vector![1, 2,];
point![1, 2,];
dvector![1, 2,];
}
#[test]
fn matrix_trybuild_tests() {
let t = trybuild::TestCases::new();

View File

@ -1,6 +1,6 @@
[package]
name = "nalgebra-sparse"
version = "0.6.0"
version = "0.9.0"
authors = [ "Andreas Longva", "Sébastien Crozet <developer@crozet.re>" ]
edition = "2018"
description = "Sparse matrix computation based on nalgebra."
@ -24,7 +24,7 @@ io = [ "pest", "pest_derive" ]
slow-tests = []
[dependencies]
nalgebra = { version="0.30", path = "../" }
nalgebra = { version="0.32", path = "../" }
num-traits = { version = "0.2", default-features = false }
proptest = { version = "1.0", optional = true }
matrixcompare-core = { version = "0.1.0", optional = true }
@ -35,9 +35,10 @@ serde = { version = "1.0", default-features = false, features = [ "derive" ], op
[dev-dependencies]
itertools = "0.10"
matrixcompare = { version = "0.3.0", features = [ "proptest-support" ] }
nalgebra = { version="0.30", path = "../", features = ["compare"] }
nalgebra = { version="0.32", path = "../", features = ["compare"] }
tempfile = "3.3"
serde_json = "1.0"
[package.metadata.docs.rs]
# Enable certain features when building docs for docs.rs
features = [ "proptest-support", "compare" ]
features = [ "proptest-support", "compare", "io"]

1
nalgebra-sparse/LICENSE Symbolic link
View File

@ -0,0 +1 @@
../LICENSE

View File

@ -306,7 +306,7 @@ where
|val| sorted_vals.push(val),
&idx_workspace[..count],
&values_workspace[..count],
&Add::add,
Add::add,
);
let new_col_count = sorted_minor_idx.len() - sorted_ja_current_len;

View File

@ -160,6 +160,25 @@ impl<T> CooMatrix<T> {
}
}
/// Try to construct a COO matrix from the given dimensions and a finite iterator of
/// (i, j, v) triplets.
///
/// Returns an error if either row or column indices contain indices out of bounds.
/// Note that the COO format inherently supports duplicate entries, but they are not
/// eagerly summed.
///
/// Implementation note:
/// Calls try_from_triplets so each value is scanned twice.
pub fn try_from_triplets_iter(
nrows: usize,
ncols: usize,
triplets: impl IntoIterator<Item = (usize, usize, T)>,
) -> Result<Self, SparseFormatError> {
let (row_indices, (col_indices, values)) =
triplets.into_iter().map(|(r, c, v)| (r, (c, v))).unzip();
Self::try_from_triplets(nrows, ncols, row_indices, col_indices, values)
}
/// An iterator over triplets (i, j, v).
// TODO: Consider giving the iterator a concrete type instead of impl trait...?
pub fn triplet_iter(&self) -> impl Iterator<Item = (usize, usize, &T)> {
@ -170,6 +189,16 @@ impl<T> CooMatrix<T> {
.map(|((i, j), v)| (*i, *j, v))
}
/// A mutable iterator over triplets (i, j, v).
// TODO: Consider giving the iterator a concrete type instead of impl trait...?
pub fn triplet_iter_mut(&mut self) -> impl Iterator<Item = (usize, usize, &mut T)> {
self.row_indices
.iter()
.zip(&self.col_indices)
.zip(self.values.iter_mut())
.map(|((i, j), v)| (*i, *j, v))
}
/// Reserves capacity for COO matrix by at least `additional` elements.
///
/// This increase the capacities of triplet holding arrays by reserving more space to avoid
@ -211,6 +240,13 @@ impl<T> CooMatrix<T> {
self.values.push(v);
}
/// Clear all triplets from the matrix.
pub fn clear_triplets(&mut self) {
self.col_indices.clear();
self.row_indices.clear();
self.values.clear();
}
/// The number of rows in the matrix.
#[inline]
#[must_use]

View File

@ -1,4 +1,3 @@
use std::mem::replace;
use std::ops::Range;
use num_traits::One;
@ -226,6 +225,15 @@ impl<T> CsMatrix<T> {
}
}
impl<T> Default for CsMatrix<T> {
fn default() -> Self {
Self {
sparsity_pattern: Default::default(),
values: vec![],
}
}
}
impl<T: Scalar + One> CsMatrix<T> {
#[inline]
pub fn identity(n: usize) -> Self {
@ -360,7 +368,7 @@ where
if let Some(minor_indices) = lane {
let count = minor_indices.len();
let remaining = replace(&mut self.remaining_values, &mut []);
let remaining = std::mem::take(&mut self.remaining_values);
let (values_in_lane, remaining) = remaining.split_at_mut(count);
self.remaining_values = remaining;
self.current_lane_idx += 1;
@ -494,7 +502,7 @@ where
assert_eq!(source_minor_indices.len(), values.len());
let nnz = values.len();
// Count the number of occurences of each minor index
// Count the number of occurrences of each minor index
let mut minor_counts = vec![0; minor_dim];
for minor_idx in source_minor_indices {
minor_counts[*minor_idx] += 1;
@ -569,7 +577,7 @@ where
} else if sort {
unreachable!("Internal error: Sorting currently not supported if no values are present.");
}
if major_offsets.len() == 0 {
if major_offsets.is_empty() {
return Err(SparseFormatError::from_kind_and_msg(
SparseFormatErrorKind::InvalidStructure,
"Number of offsets should be greater than 0.",
@ -615,12 +623,12 @@ where
));
}
let minor_idx_in_lane = minor_indices.get(range_start..range_end).ok_or(
let minor_idx_in_lane = minor_indices.get(range_start..range_end).ok_or_else(|| {
SparseFormatError::from_kind_and_msg(
SparseFormatErrorKind::IndexOutOfBounds,
"A major offset is out of bounds.",
),
)?;
)
})?;
// We test for in-bounds, uniqueness and monotonicity at the same time
// to ensure that we only visit each minor index once
@ -653,9 +661,9 @@ where
if !monotonic && sort {
let range_size = range_end - range_start;
minor_index_permutation.resize(range_size, 0);
compute_sort_permutation(&mut minor_index_permutation, &minor_idx_in_lane);
compute_sort_permutation(&mut minor_index_permutation, minor_idx_in_lane);
minor_idx_buffer.clear();
minor_idx_buffer.extend_from_slice(&minor_idx_in_lane);
minor_idx_buffer.extend_from_slice(minor_idx_in_lane);
apply_permutation(
&mut minor_indices[range_start..range_end],
&minor_idx_buffer,

View File

@ -24,6 +24,7 @@ use std::slice::{Iter, IterMut};
/// # Usage
///
/// ```
/// use nalgebra_sparse::coo::CooMatrix;
/// use nalgebra_sparse::csc::CscMatrix;
/// use nalgebra::{DMatrix, Matrix3x4};
/// use matrixcompare::assert_matrix_eq;
@ -32,8 +33,9 @@ use std::slice::{Iter, IterMut};
/// // change the sparsity pattern of the matrix after it has been constructed. The easiest
/// // way to construct a CSC matrix is to first incrementally construct a COO matrix,
/// // and then convert it to CSC.
/// # use nalgebra_sparse::coo::CooMatrix;
/// # let coo = CooMatrix::<f64>::new(3, 3);
///
/// let mut coo = CooMatrix::<f64>::new(3, 3);
/// coo.push(2, 0, 1.0);
/// let csc = CscMatrix::from(&coo);
///
/// // Alternatively, a CSC matrix can be constructed directly from raw CSC data.
@ -156,7 +158,7 @@ impl<T> CscMatrix<T> {
/// an error is returned to indicate the failure.
///
/// An error is returned if the data given does not conform to the CSC storage format.
/// See the documentation for [CscMatrix](struct.CscMatrix.html) for more information.
/// See the documentation for [`CscMatrix`] for more information.
pub fn try_from_csc_data(
num_rows: usize,
num_cols: usize,
@ -182,7 +184,7 @@ impl<T> CscMatrix<T> {
///
/// An error is returned if the data given does not conform to the CSC storage format
/// with the exception of having unsorted row indices and values.
/// See the documentation for [CscMatrix](struct.CscMatrix.html) for more information.
/// See the documentation for [`CscMatrix`] for more information.
pub fn try_from_unsorted_csc_data(
num_rows: usize,
num_cols: usize,
@ -572,6 +574,14 @@ impl<T> CscMatrix<T> {
}
}
impl<T> Default for CscMatrix<T> {
fn default() -> Self {
Self {
cs: Default::default(),
}
}
}
/// Convert pattern format errors into more meaningful CSC-specific errors.
///
/// This ensures that the terminology is consistent: we are talking about rows and columns,
@ -615,6 +625,15 @@ pub struct CscTripletIter<'a, T> {
values_iter: Iter<'a, T>,
}
impl<'a, T> Clone for CscTripletIter<'a, T> {
fn clone(&self) -> Self {
CscTripletIter {
pattern_iter: self.pattern_iter.clone(),
values_iter: self.values_iter.clone(),
}
}
}
impl<'a, T: Clone> CscTripletIter<'a, T> {
/// Adapts the triplet iterator to return owned values.
///
@ -746,7 +765,7 @@ impl<'a, T> CscColMut<'a, T> {
}
}
/// Column iterator for [CscMatrix](struct.CscMatrix.html).
/// Column iterator for [`CscMatrix`].
pub struct CscColIter<'a, T> {
lane_iter: CsLaneIter<'a, T>,
}
@ -759,7 +778,7 @@ impl<'a, T> Iterator for CscColIter<'a, T> {
}
}
/// Mutable column iterator for [CscMatrix](struct.CscMatrix.html).
/// Mutable column iterator for [`CscMatrix`].
pub struct CscColIterMut<'a, T> {
lane_iter: CsLaneIterMut<'a, T>,
}

View File

@ -25,6 +25,7 @@ use std::slice::{Iter, IterMut};
/// # Usage
///
/// ```
/// use nalgebra_sparse::coo::CooMatrix;
/// use nalgebra_sparse::csr::CsrMatrix;
/// use nalgebra::{DMatrix, Matrix3x4};
/// use matrixcompare::assert_matrix_eq;
@ -33,8 +34,9 @@ use std::slice::{Iter, IterMut};
/// // change the sparsity pattern of the matrix after it has been constructed. The easiest
/// // way to construct a CSR matrix is to first incrementally construct a COO matrix,
/// // and then convert it to CSR.
/// # use nalgebra_sparse::coo::CooMatrix;
/// # let coo = CooMatrix::<f64>::new(3, 3);
///
/// let mut coo = CooMatrix::<f64>::new(3, 3);
/// coo.push(2, 0, 1.0);
/// let csr = CsrMatrix::from(&coo);
///
/// // Alternatively, a CSR matrix can be constructed directly from raw CSR data.
@ -157,7 +159,7 @@ impl<T> CsrMatrix<T> {
/// an error is returned to indicate the failure.
///
/// An error is returned if the data given does not conform to the CSR storage format.
/// See the documentation for [CsrMatrix](struct.CsrMatrix.html) for more information.
/// See the documentation for [`CsrMatrix`] for more information.
pub fn try_from_csr_data(
num_rows: usize,
num_cols: usize,
@ -183,7 +185,7 @@ impl<T> CsrMatrix<T> {
///
/// An error is returned if the data given does not conform to the CSR storage format
/// with the exception of having unsorted column indices and values.
/// See the documentation for [CsrMatrix](struct.CsrMatrix.html) for more information.
/// See the documentation for [`CsrMatrix`] for more information.
pub fn try_from_unsorted_csr_data(
num_rows: usize,
num_cols: usize,
@ -573,6 +575,14 @@ impl<T> CsrMatrix<T> {
}
}
impl<T> Default for CsrMatrix<T> {
fn default() -> Self {
Self {
cs: Default::default(),
}
}
}
/// Convert pattern format errors into more meaningful CSR-specific errors.
///
/// This ensures that the terminology is consistent: we are talking about rows and columns,
@ -616,6 +626,15 @@ pub struct CsrTripletIter<'a, T> {
values_iter: Iter<'a, T>,
}
impl<'a, T> Clone for CsrTripletIter<'a, T> {
fn clone(&self) -> Self {
CsrTripletIter {
pattern_iter: self.pattern_iter.clone(),
values_iter: self.values_iter.clone(),
}
}
}
impl<'a, T: Clone> CsrTripletIter<'a, T> {
/// Adapts the triplet iterator to return owned values.
///
@ -751,7 +770,7 @@ impl<'a, T> CsrRowMut<'a, T> {
}
}
/// Row iterator for [CsrMatrix](struct.CsrMatrix.html).
/// Row iterator for [`CsrMatrix`].
pub struct CsrRowIter<'a, T> {
lane_iter: CsLaneIter<'a, T>,
}
@ -764,7 +783,7 @@ impl<'a, T> Iterator for CsrRowIter<'a, T> {
}
}
/// Mutable row iterator for [CsrMatrix](struct.CsrMatrix.html).
/// Mutable row iterator for [`CsrMatrix`].
pub struct CsrRowIterMut<'a, T> {
lane_iter: CsLaneIterMut<'a, T>,
}

View File

@ -3,7 +3,7 @@ use crate::ops::serial::spsolve_csc_lower_triangular;
use crate::ops::Op;
use crate::pattern::SparsityPattern;
use core::{iter, mem};
use nalgebra::{DMatrix, DMatrixSlice, DMatrixSliceMut, RealField};
use nalgebra::{DMatrix, DMatrixView, DMatrixViewMut, RealField};
use std::fmt::{Display, Formatter};
/// A symbolic sparse Cholesky factorization of a CSC matrix.
@ -264,7 +264,7 @@ impl<T: RealField> CscCholesky<T> {
///
/// Panics if `B` is not square.
#[must_use = "Did you mean to use solve_mut()?"]
pub fn solve<'a>(&'a self, b: impl Into<DMatrixSlice<'a, T>>) -> DMatrix<T> {
pub fn solve<'a>(&'a self, b: impl Into<DMatrixView<'a, T>>) -> DMatrix<T> {
let b = b.into();
let mut output = b.clone_owned();
self.solve_mut(&mut output);
@ -278,7 +278,7 @@ impl<T: RealField> CscCholesky<T> {
/// # Panics
///
/// Panics if `b` is not square.
pub fn solve_mut<'a>(&'a self, b: impl Into<DMatrixSliceMut<'a, T>>) {
pub fn solve_mut<'a>(&'a self, b: impl Into<DMatrixViewMut<'a, T>>) {
let expect_msg = "If the Cholesky factorization succeeded,\
then the triangular solve should never fail";
// Solve LY = B

View File

@ -1,9 +1,9 @@
//! Implementation of matrix market io code.
//!
//! See the [website](https://math.nist.gov/MatrixMarket/formats.html) or the [paper](https://www.researchgate.net/publication/2630533_The_Matrix_Market_Exchange_Formats_Initial_Design) for more details about matrix market.
use crate::coo::CooMatrix;
use crate::SparseFormatError;
use crate::SparseFormatErrorKind;
use crate::{CooMatrix, CscMatrix, CsrMatrix};
use nalgebra::Complex;
use pest::iterators::Pairs;
use pest::Parser;
@ -12,7 +12,8 @@ use std::convert::Infallible;
use std::convert::TryFrom;
use std::fmt;
use std::fmt::Formatter;
use std::fs;
use std::fs::{self, File};
use std::io::{BufWriter, Write};
use std::num::ParseIntError;
use std::num::TryFromIntError;
use std::path::Path;
@ -267,7 +268,7 @@ impl fmt::Display for MatrixMarketError {
write!(f, "InvalidHeader,")?;
}
MatrixMarketErrorKind::EntryMismatch => {
write!(f, "EntryNumUnmatched,")?;
write!(f, "EntryMismatch,")?;
}
MatrixMarketErrorKind::TypeMismatch => {
write!(f, "TypeMismatch,")?;
@ -288,7 +289,7 @@ impl fmt::Display for MatrixMarketError {
write!(f, "NotLowerTriangle,")?;
}
MatrixMarketErrorKind::NonSquare => {
write!(f, "NotSquareMatrix,")?;
write!(f, "NonSquare,")?;
}
}
write!(f, " message: {}", self.message)
@ -506,6 +507,21 @@ mod internal {
fn negative(self) -> Result<Self, MatrixMarketError>;
/// When matrix is a Hermitian matrix, it will convert itself to its conjugate.
fn conjugate(self) -> Result<Self, MatrixMarketError>;
/// Returns the name of SupportedMatrixMarketScalar, used when write the matrix
fn typename() -> &'static str;
/// Write the data self to w
fn write_matrix_market<W: std::fmt::Write>(&self, w: W) -> Result<(), std::fmt::Error>;
}
pub trait SupportedMatrixMarketExport<T: SupportedMatrixMarketScalar> {
/// iterate over triplets
fn triplet_iter(&self) -> Box<dyn Iterator<Item = (usize, usize, &T)> + '_>;
/// number of rows
fn nrows(&self) -> usize;
/// number of columns
fn ncols(&self) -> usize;
/// number of non-zeros
fn nnz(&self) -> usize;
}
}
@ -557,6 +573,17 @@ macro_rules! mm_int_impl {
fn negative(self) -> Result<Self, MatrixMarketError> {
Ok(-self)
}
#[inline]
fn typename() -> &'static str {
"integer"
}
#[inline]
fn write_matrix_market<W: std::fmt::Write>(
&self,
mut w: W,
) -> Result<(), std::fmt::Error> {
write!(w, "{}", self)
}
}
};
}
@ -602,6 +629,17 @@ macro_rules! mm_real_impl {
fn negative(self) -> Result<Self, MatrixMarketError> {
Ok(-self)
}
#[inline]
fn typename() -> &'static str {
"real"
}
#[inline]
fn write_matrix_market<W: std::fmt::Write>(
&self,
mut w: W,
) -> Result<(), std::fmt::Error> {
write!(w, "{}", self)
}
}
};
}
@ -648,6 +686,17 @@ macro_rules! mm_complex_impl {
fn negative(self) -> Result<Self, MatrixMarketError> {
Ok(-self)
}
#[inline]
fn typename() -> &'static str {
"complex"
}
#[inline]
fn write_matrix_market<W: std::fmt::Write>(
&self,
mut w: W,
) -> Result<(), std::fmt::Error> {
write!(w, "{} {}", self.re, self.im)
}
}
};
}
@ -697,6 +746,17 @@ macro_rules! mm_pattern_impl {
format!("Pattern type has no negative"),
))
}
#[inline]
fn typename() -> &'static str {
"pattern"
}
#[inline]
fn write_matrix_market<W: std::fmt::Write>(
&self,
mut _w: W,
) -> Result<(), std::fmt::Error> {
Ok(())
}
}
};
}
@ -715,6 +775,46 @@ mm_complex_impl!(f64);
mm_pattern_impl!(());
/// A marker trait for sparse matrix types that can be exported to the matrix market format.
///
/// This is a sealed trait; it cannot be implemented by external crates. This is done in order to prevent leaking
/// some of the implementation details we currently rely on. We may relax this restriction in the future.
pub trait MatrixMarketExport<T: MatrixMarketScalar>:
internal::SupportedMatrixMarketExport<T>
{
}
macro_rules! mm_matrix_impl {
($T_MATRIX:ty) => {
impl<T: MatrixMarketScalar> MatrixMarketExport<T> for $T_MATRIX {}
impl<T: internal::SupportedMatrixMarketScalar> internal::SupportedMatrixMarketExport<T>
for $T_MATRIX
{
#[inline]
fn triplet_iter(&self) -> Box<dyn Iterator<Item = (usize, usize, &T)> + '_> {
Box::new(self.triplet_iter())
}
#[inline]
fn nrows(&self) -> usize {
self.nrows()
}
#[inline]
fn ncols(&self) -> usize {
self.ncols()
}
#[inline]
fn nnz(&self) -> usize {
self.nnz()
}
}
};
}
mm_matrix_impl!(CooMatrix<T>);
mm_matrix_impl!(CsrMatrix<T>);
mm_matrix_impl!(CscMatrix<T>);
#[derive(Parser)]
#[grammar = "io/matrix_market.pest"]
struct MatrixMarketParser;
@ -1329,3 +1429,123 @@ fn next_dense_coordinate(
}
}
}
/// Save a sparse matrix as a Matrix Market format string.
///
/// The exporter only writes the matrix into `coordinate` and `general` format.
///
///
/// Examples
/// --------
/// ```
/// # use nalgebra_sparse::CooMatrix;
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use nalgebra_sparse::io::{save_to_matrix_market_str};
/// let expected_str = r#"%%matrixmarket matrix coordinate integer general
/// % matrixmarket file generated by nalgebra-sparse.
/// 5 4 2
/// 1 1 10
/// 2 3 5
/// "#;
/// let row_indices = vec![0,1];
/// let col_indices = vec![0,2];
/// let values = vec![10,5];
/// let matrix = CooMatrix::try_from_triplets(5,4,row_indices,col_indices,values)?;
/// let generated_matrixmarket_str = save_to_matrix_market_str(&matrix);
/// assert_eq!(expected_str,generated_matrixmarket_str);
/// # Ok(()) }
/// ```
pub fn save_to_matrix_market_str<T, S>(sparse_matrix: &S) -> String
where
T: MatrixMarketScalar,
S: MatrixMarketExport<T>,
{
let mut bytes = Vec::<u8>::new();
// This will call impl<A: Allocator> Write for Vec<u8, A>
// The vector will grow as needed.
// So, unwrap here won't cause any issue.
save_to_matrix_market(&mut bytes, sparse_matrix).unwrap();
String::from_utf8(bytes)
.expect("Unexpected non UTF-8 data was generated when export to matrix market string")
}
/// Save a sparse matrix to a Matrix Market format file.
///
/// The exporter only saves the matrix with the `coordinate` and `general` matrix market formats.
///
/// Errors
/// --------
///
/// See [MatrixMarketErrorKind] for a list of possible error conditions.
///
/// Examples
/// --------
/// ```no_run
/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
/// use nalgebra_sparse::io::{save_to_matrix_market_file,load_coo_from_matrix_market_str};
/// let str = r#"
/// %%matrixmarket matrix coordinate integer general
/// 5 4 2
/// 1 1 10
/// 2 3 5
/// "#;
/// let matrix = load_coo_from_matrix_market_str::<i32>(&str)?;
/// save_to_matrix_market_file(&matrix,"path/to/matrix.mtx")?;
/// # Ok(()) }
/// ```
pub fn save_to_matrix_market_file<T, S, P>(sparse_matrix: &S, path: P) -> Result<(), std::io::Error>
where
T: MatrixMarketScalar,
S: MatrixMarketExport<T>,
P: AsRef<Path>,
{
let file = File::create(path)?;
let mut file = BufWriter::new(file);
save_to_matrix_market(&mut file, sparse_matrix)?;
// Quote from BufWriter doc.
// > It is critical to call flush before BufWriter<W> is dropped. Though dropping will attempt to flush the contents of the buffer, any errors that happen in the process of dropping will be ignored. Calling flush ensures that the buffer is empty and thus dropping will not even attempt file operations.
file.flush()
.expect("Unexpected error when flushing the buffer data to File");
Ok(())
}
/// Save a sparse matrix to an [std::io::Write] instance.
///
/// This is the most general save functionality. See [save_to_matrix_market_file] and
/// [save_to_matrix_market_str] for higher-level functionality.
pub fn save_to_matrix_market<T, S, W>(mut w: W, sparse_matrix: &S) -> Result<(), std::io::Error>
where
T: MatrixMarketScalar,
S: MatrixMarketExport<T>,
W: Write,
{
// write header
writeln!(
w,
"%%matrixmarket matrix coordinate {} general",
T::typename()
)?;
//write comment
writeln!(w, "% matrixmarket file generated by nalgebra-sparse.")?;
// write shape information
writeln!(
w,
"{} {} {}",
sparse_matrix.nrows(),
sparse_matrix.ncols(),
sparse_matrix.nnz()
)?;
//write triplets
let mut buffer = String::new();
for (r, c, d) in sparse_matrix.triplet_iter() {
buffer.clear();
d.write_matrix_market(&mut buffer)
.expect("Unexpected format error was generated when write to String");
writeln!(w, "{} {} {}", r + 1, c + 1, buffer)?;
}
Ok(())
}

View File

@ -6,7 +6,7 @@
//!
//! | Format | Import | Export |
//! | ------------------------------------------------|------------|------------|
//! | [Matrix market](#matrix-market-format) | Yes | No |
//! | [Matrix market](#matrix-market-format) | Yes | Yes |
//!
//! [Matrix market]: https://math.nist.gov/MatrixMarket/formats.html
//!
@ -19,10 +19,12 @@
//! which also uses the Matrix Market file format.
//!
//! We currently offer functionality for importing a Matrix market file to an instance of a
//! [CooMatrix](crate::CooMatrix) through the function [load_coo_from_matrix_market_file]. It is also possible to load
//! a matrix stored in the matrix market format with the function [load_coo_from_matrix_market_str].
//!
//! Export is currently not implemented, but [planned](https://github.com/dimforge/nalgebra/issues/1037).
//! [CooMatrix](crate::CooMatrix) through the function [load_coo_from_matrix_market_file],
//! as well as functionality for writing various sparse matrices to the matrix market format
//! through [save_to_matrix_market_file]. It is also possible to load
//! a matrix stored as a string in the matrix market format with the function
//! [load_coo_from_matrix_market_str], or similarly write to a string with
//! [save_to_matrix_market_str].
//!
//! Our implementation is based on the [format description](https://math.nist.gov/MatrixMarket/formats.html)
//! on the Matrix Market website and the
@ -32,7 +34,8 @@
//! > "*The Matrix Market Exchange Formats: Initial Design.*" (1996).
pub use self::matrix_market::{
load_coo_from_matrix_market_file, load_coo_from_matrix_market_str, MatrixMarketError,
MatrixMarketErrorKind, MatrixMarketScalar,
load_coo_from_matrix_market_file, load_coo_from_matrix_market_str, save_to_matrix_market,
save_to_matrix_market_file, save_to_matrix_market_str, MatrixMarketError,
MatrixMarketErrorKind, MatrixMarketExport, MatrixMarketScalar,
};
mod matrix_market;

View File

@ -143,8 +143,6 @@
)]
pub extern crate nalgebra as na;
#[cfg(feature = "io")]
extern crate pest;
#[macro_use]
#[cfg(feature = "io")]
extern crate pest_derive;
@ -201,7 +199,7 @@ impl SparseFormatError {
}
}
/// The type of format error described by a [SparseFormatError](struct.SparseFormatError.html).
/// The type of format error described by a [`SparseFormatError`].
#[non_exhaustive]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SparseFormatErrorKind {

View File

@ -3,14 +3,14 @@ use crate::csr::CsrMatrix;
use crate::ops::serial::{
spadd_csc_prealloc, spadd_csr_prealloc, spadd_pattern, spmm_csc_dense, spmm_csc_pattern,
spmm_csc_prealloc, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc,
spmm_csc_prealloc_unchecked, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc_unchecked,
};
use crate::ops::Op;
use nalgebra::allocator::Allocator;
use nalgebra::base::storage::RawStorage;
use nalgebra::constraint::{DimEq, ShapeConstraint};
use nalgebra::{
ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, DefaultAllocator, Dim, Dynamic, Matrix, OMatrix,
ClosedAdd, ClosedDiv, ClosedMul, ClosedSub, DefaultAllocator, Dim, Dyn, Matrix, OMatrix,
Scalar, U1,
};
use num_traits::{One, Zero};
@ -59,7 +59,7 @@ macro_rules! impl_sp_plus_minus {
let mut result = $matrix_type::try_from_pattern_and_values(pattern, values)
.unwrap();
$spadd_fn(T::zero(), &mut result, T::one(), Op::NoOp(&a)).unwrap();
$spadd_fn(T::one(), &mut result, $factor * T::one(), Op::NoOp(&b)).unwrap();
$spadd_fn(T::one(), &mut result, $factor, Op::NoOp(&b)).unwrap();
result
});
@ -112,9 +112,9 @@ macro_rules! impl_spmm {
}
}
impl_spmm!(CsrMatrix, spmm_csr_pattern, spmm_csr_prealloc);
impl_spmm!(CsrMatrix, spmm_csr_pattern, spmm_csr_prealloc_unchecked);
// Need to switch order of operations for CSC pattern
impl_spmm!(CscMatrix, spmm_csc_pattern, spmm_csc_prealloc);
impl_spmm!(CscMatrix, spmm_csc_pattern, spmm_csc_prealloc_unchecked);
/// Implements Scalar * Matrix operations for *concrete* scalar types. The reason this is necessary
/// is that we are not able to implement Mul<Matrix<T>> for all T generically due to orphan rules.
@ -273,8 +273,8 @@ macro_rules! impl_spmm_cs_dense {
// Implement ref-ref
impl_spmm_cs_dense!(&'a $matrix_type_name<T>, &'a Matrix<T, R, C, S>, $spmm_fn, |lhs, rhs| {
let (_, ncols) = rhs.shape_generic();
let nrows = Dynamic::new(lhs.nrows());
let mut result = OMatrix::<T, Dynamic, C>::zeros_generic(nrows, ncols);
let nrows = Dyn(lhs.nrows());
let mut result = OMatrix::<T, Dyn, C>::zeros_generic(nrows, ncols);
$spmm_fn(T::zero(), &mut result, T::one(), Op::NoOp(lhs), Op::NoOp(rhs));
result
});
@ -302,21 +302,21 @@ macro_rules! impl_spmm_cs_dense {
R: Dim,
C: Dim,
S: RawStorage<T, R, C>,
DefaultAllocator: Allocator<T, Dynamic, C>,
DefaultAllocator: Allocator<T, Dyn, C>,
// TODO: Is it possible to simplify these bounds?
ShapeConstraint:
// Bounds so that we can turn OMatrix<T, Dynamic, C> into a DMatrixSliceMut
DimEq<U1, <<DefaultAllocator as Allocator<T, Dynamic, C>>::Buffer as RawStorage<T, Dynamic, C>>::RStride>
+ DimEq<C, Dynamic>
+ DimEq<Dynamic, <<DefaultAllocator as Allocator<T, Dynamic, C>>::Buffer as RawStorage<T, Dynamic, C>>::CStride>
// Bounds so that we can turn OMatrix<T, Dyn, C> into a DMatrixSliceMut
DimEq<U1, <<DefaultAllocator as Allocator<T, Dyn, C>>::Buffer as RawStorage<T, Dyn, C>>::RStride>
+ DimEq<C, Dyn>
+ DimEq<Dyn, <<DefaultAllocator as Allocator<T, Dyn, C>>::Buffer as RawStorage<T, Dyn, C>>::CStride>
// Bounds so that we can turn &Matrix<T, R, C, S> into a DMatrixSlice
+ DimEq<U1, S::RStride>
+ DimEq<R, Dynamic>
+ DimEq<Dynamic, S::CStride>
+ DimEq<R, Dyn>
+ DimEq<Dyn, S::CStride>
{
// We need the column dimension to be generic, so that if RHS is a vector, then
// we also get a vector (and not a matrix)
type Output = OMatrix<T, Dynamic, C>;
type Output = OMatrix<T, Dyn, C>;
fn mul(self, rhs: $dense_matrix_type) -> Self::Output {
let $lhs = self;

View File

@ -149,8 +149,8 @@ impl<T> Op<T> {
#[must_use]
pub fn as_ref(&self) -> Op<&T> {
match self {
Op::NoOp(obj) => Op::NoOp(&obj),
Op::Transpose(obj) => Op::Transpose(&obj),
Op::NoOp(obj) => Op::NoOp(obj),
Op::Transpose(obj) => Op::Transpose(obj),
}
}

View File

@ -2,7 +2,7 @@ use crate::cs::CsMatrix;
use crate::ops::serial::{OperationError, OperationErrorKind};
use crate::ops::Op;
use crate::SparseEntryMut;
use nalgebra::{ClosedAdd, ClosedMul, DMatrixSlice, DMatrixSliceMut, Scalar};
use nalgebra::{ClosedAdd, ClosedMul, DMatrixView, DMatrixViewMut, Scalar};
use num_traits::{One, Zero};
fn spmm_cs_unexpected_entry() -> OperationError {
@ -20,6 +20,51 @@ fn spmm_cs_unexpected_entry() -> OperationError {
/// reversed (since transpose(AB) = transpose(B) * transpose(A) and CSC(A) = transpose(CSR(A)).
///
/// We assume here that the matrices have already been verified to be dimensionally compatible.
pub fn spmm_cs_prealloc_unchecked<T>(
beta: T,
c: &mut CsMatrix<T>,
alpha: T,
a: &CsMatrix<T>,
b: &CsMatrix<T>,
) -> Result<(), OperationError>
where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
assert_eq!(c.pattern().major_dim(), a.pattern().major_dim());
assert_eq!(c.pattern().minor_dim(), b.pattern().minor_dim());
let some_val = Zero::zero();
let mut scratchpad_values: Vec<T> = vec![some_val; b.pattern().minor_dim()];
for i in 0..c.pattern().major_dim() {
let a_lane_i = a.get_lane(i).unwrap();
let mut c_lane_i = c.get_lane_mut(i).unwrap();
for (&k, a_ik) in a_lane_i.minor_indices().iter().zip(a_lane_i.values()) {
let b_lane_k = b.get_lane(k).unwrap();
let alpha_aik = alpha.clone() * a_ik.clone();
for (j, b_kj) in b_lane_k.minor_indices().iter().zip(b_lane_k.values()) {
// use a dense scatter vector to accumulate non-zeros quickly
unsafe {
*scratchpad_values.get_unchecked_mut(*j) += alpha_aik.clone() * b_kj.clone();
}
}
}
//Get indices from C pattern and gather from the dense scratchpad_values
let (indices, values) = c_lane_i.indices_and_values_mut();
values
.iter_mut()
.zip(indices)
.for_each(|(output_ref, index)| unsafe {
*output_ref = beta.clone() * output_ref.clone()
+ scratchpad_values.get_unchecked(*index).clone();
*scratchpad_values.get_unchecked_mut(*index) = Zero::zero();
});
}
Ok(())
}
pub fn spmm_cs_prealloc<T>(
beta: T,
c: &mut CsMatrix<T>,
@ -131,10 +176,10 @@ where
/// the transposed operation must be specified for the CSC matrix.
pub fn spmm_cs_dense<T>(
beta: T,
mut c: DMatrixSliceMut<'_, T>,
mut c: DMatrixViewMut<'_, T>,
alpha: T,
a: Op<&CsMatrix<T>>,
b: Op<DMatrixSlice<'_, T>>,
b: Op<DMatrixView<'_, T>>,
) where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{

View File

@ -1,8 +1,10 @@
use crate::csc::CscMatrix;
use crate::ops::serial::cs::{spadd_cs_prealloc, spmm_cs_dense, spmm_cs_prealloc};
use crate::ops::serial::cs::{
spadd_cs_prealloc, spmm_cs_dense, spmm_cs_prealloc, spmm_cs_prealloc_unchecked,
};
use crate::ops::serial::{OperationError, OperationErrorKind};
use crate::ops::Op;
use nalgebra::{ClosedAdd, ClosedMul, DMatrixSlice, DMatrixSliceMut, RealField, Scalar};
use nalgebra::{ClosedAdd, ClosedMul, DMatrixView, DMatrixViewMut, RealField, Scalar};
use num_traits::{One, Zero};
use std::borrow::Cow;
@ -14,10 +16,10 @@ use std::borrow::Cow;
/// Panics if the dimensions of the matrices involved are not compatible with the expression.
pub fn spmm_csc_dense<'a, T>(
beta: T,
c: impl Into<DMatrixSliceMut<'a, T>>,
c: impl Into<DMatrixViewMut<'a, T>>,
alpha: T,
a: Op<&CscMatrix<T>>,
b: Op<impl Into<DMatrixSlice<'a, T>>>,
b: Op<impl Into<DMatrixView<'a, T>>>,
) where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
@ -27,10 +29,10 @@ pub fn spmm_csc_dense<'a, T>(
fn spmm_csc_dense_<T>(
beta: T,
c: DMatrixSliceMut<'_, T>,
c: DMatrixViewMut<'_, T>,
alpha: T,
a: Op<&CscMatrix<T>>,
b: Op<DMatrixSlice<'_, T>>,
b: Op<DMatrixView<'_, T>>,
) where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
@ -83,14 +85,65 @@ where
{
assert_compatible_spmm_dims!(c, a, b);
use Op::{NoOp, Transpose};
use Op::NoOp;
match (&a, &b) {
(NoOp(ref a), NoOp(ref b)) => {
(NoOp(a), NoOp(b)) => {
// Note: We have to reverse the order for CSC matrices
spmm_cs_prealloc(beta, &mut c.cs, alpha, &b.cs, &a.cs)
}
_ => {
_ => spmm_csc_transposed(beta, c, alpha, a, b, spmm_csc_prealloc),
}
}
/// Faster sparse-sparse matrix multiplication, `C <- beta * C + alpha * op(A) * op(B)`.
/// This will not return an error even if the patterns don't match.
/// Should be used for situations where pattern creation immediately precedes multiplication.
///
/// Panics if the dimensions of the matrices involved are not compatible with the expression.
pub fn spmm_csc_prealloc_unchecked<T>(
beta: T,
c: &mut CscMatrix<T>,
alpha: T,
a: Op<&CscMatrix<T>>,
b: Op<&CscMatrix<T>>,
) -> Result<(), OperationError>
where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
assert_compatible_spmm_dims!(c, a, b);
use Op::NoOp;
match (&a, &b) {
(NoOp(a), NoOp(b)) => {
// Note: We have to reverse the order for CSC matrices
spmm_cs_prealloc_unchecked(beta, &mut c.cs, alpha, &b.cs, &a.cs)
}
_ => spmm_csc_transposed(beta, c, alpha, a, b, spmm_csc_prealloc_unchecked),
}
}
fn spmm_csc_transposed<T, F>(
beta: T,
c: &mut CscMatrix<T>,
alpha: T,
a: Op<&CscMatrix<T>>,
b: Op<&CscMatrix<T>>,
spmm_kernel: F,
) -> Result<(), OperationError>
where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
F: Fn(
T,
&mut CscMatrix<T>,
T,
Op<&CscMatrix<T>>,
Op<&CscMatrix<T>>,
) -> Result<(), OperationError>,
{
use Op::{NoOp, Transpose};
// Currently we handle transposition by explicitly precomputing transposed matrices
// and calling the operation again without transposition
let a_ref: &CscMatrix<T> = a.inner_ref();
@ -99,17 +152,12 @@ where
use Cow::*;
match (&a, &b) {
(NoOp(_), NoOp(_)) => unreachable!(),
(Transpose(ref a), NoOp(_)) => (Owned(a.transpose()), Borrowed(b_ref)),
(NoOp(_), Transpose(ref b)) => (Borrowed(a_ref), Owned(b.transpose())),
(Transpose(ref a), Transpose(ref b)) => {
(Owned(a.transpose()), Owned(b.transpose()))
}
(Transpose(a), NoOp(_)) => (Owned(a.transpose()), Borrowed(b_ref)),
(NoOp(_), Transpose(b)) => (Borrowed(a_ref), Owned(b.transpose())),
(Transpose(a), Transpose(b)) => (Owned(a.transpose()), Owned(b.transpose())),
}
};
spmm_csc_prealloc(beta, c, alpha, NoOp(a.as_ref()), NoOp(b.as_ref()))
}
}
spmm_kernel(beta, c, alpha, NoOp(a.as_ref()), NoOp(b.as_ref()))
}
/// Solve the lower triangular system `op(L) X = B`.
@ -125,7 +173,7 @@ where
/// Panics if `L` is not square, or if `L` and `B` are not dimensionally compatible.
pub fn spsolve_csc_lower_triangular<'a, T: RealField>(
l: Op<&CscMatrix<T>>,
b: impl Into<DMatrixSliceMut<'a, T>>,
b: impl Into<DMatrixViewMut<'a, T>>,
) -> Result<(), OperationError> {
let b = b.into();
let l_matrix = l.into_inner();
@ -147,7 +195,7 @@ pub fn spsolve_csc_lower_triangular<'a, T: RealField>(
fn spsolve_csc_lower_triangular_no_transpose<T: RealField>(
l: &CscMatrix<T>,
b: DMatrixSliceMut<'_, T>,
b: DMatrixViewMut<'_, T>,
) -> Result<(), OperationError> {
let mut x = b;
@ -205,7 +253,7 @@ fn spsolve_encountered_zero_diagonal() -> Result<(), OperationError> {
fn spsolve_csc_lower_triangular_transpose<T: RealField>(
l: &CscMatrix<T>,
b: DMatrixSliceMut<'_, T>,
b: DMatrixViewMut<'_, T>,
) -> Result<(), OperationError> {
let mut x = b;

View File

@ -1,18 +1,20 @@
use crate::csr::CsrMatrix;
use crate::ops::serial::cs::{spadd_cs_prealloc, spmm_cs_dense, spmm_cs_prealloc};
use crate::ops::serial::cs::{
spadd_cs_prealloc, spmm_cs_dense, spmm_cs_prealloc, spmm_cs_prealloc_unchecked,
};
use crate::ops::serial::OperationError;
use crate::ops::Op;
use nalgebra::{ClosedAdd, ClosedMul, DMatrixSlice, DMatrixSliceMut, Scalar};
use nalgebra::{ClosedAdd, ClosedMul, DMatrixView, DMatrixViewMut, Scalar};
use num_traits::{One, Zero};
use std::borrow::Cow;
/// Sparse-dense matrix-matrix multiplication `C <- beta * C + alpha * op(A) * op(B)`.
pub fn spmm_csr_dense<'a, T>(
beta: T,
c: impl Into<DMatrixSliceMut<'a, T>>,
c: impl Into<DMatrixViewMut<'a, T>>,
alpha: T,
a: Op<&CsrMatrix<T>>,
b: Op<impl Into<DMatrixSlice<'a, T>>>,
b: Op<impl Into<DMatrixView<'a, T>>>,
) where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
@ -22,10 +24,10 @@ pub fn spmm_csr_dense<'a, T>(
fn spmm_csr_dense_<T>(
beta: T,
c: DMatrixSliceMut<'_, T>,
c: DMatrixViewMut<'_, T>,
alpha: T,
a: Op<&CsrMatrix<T>>,
b: Op<DMatrixSlice<'_, T>>,
b: Op<DMatrixView<'_, T>>,
) where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
@ -77,30 +79,71 @@ where
{
assert_compatible_spmm_dims!(c, a, b);
use Op::{NoOp, Transpose};
use Op::NoOp;
match (&a, &b) {
(NoOp(ref a), NoOp(ref b)) => spmm_cs_prealloc(beta, &mut c.cs, alpha, &a.cs, &b.cs),
_ => {
(NoOp(a), NoOp(b)) => spmm_cs_prealloc(beta, &mut c.cs, alpha, &a.cs, &b.cs),
_ => spmm_csr_transposed(beta, c, alpha, a, b, spmm_csr_prealloc),
}
}
/// Faster sparse-sparse matrix multiplication, `C <- beta * C + alpha * op(A) * op(B)`.
/// This will not return an error even if the patterns don't match.
/// Should be used for situations where pattern creation immediately precedes multiplication.
///
/// Panics if the dimensions of the matrices involved are not compatible with the expression.
pub fn spmm_csr_prealloc_unchecked<T>(
beta: T,
c: &mut CsrMatrix<T>,
alpha: T,
a: Op<&CsrMatrix<T>>,
b: Op<&CsrMatrix<T>>,
) -> Result<(), OperationError>
where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
{
assert_compatible_spmm_dims!(c, a, b);
use Op::NoOp;
match (&a, &b) {
(NoOp(a), NoOp(b)) => spmm_cs_prealloc_unchecked(beta, &mut c.cs, alpha, &a.cs, &b.cs),
_ => spmm_csr_transposed(beta, c, alpha, a, b, spmm_csr_prealloc_unchecked),
}
}
fn spmm_csr_transposed<T, F>(
beta: T,
c: &mut CsrMatrix<T>,
alpha: T,
a: Op<&CsrMatrix<T>>,
b: Op<&CsrMatrix<T>>,
spmm_kernel: F,
) -> Result<(), OperationError>
where
T: Scalar + ClosedAdd + ClosedMul + Zero + One,
F: Fn(
T,
&mut CsrMatrix<T>,
T,
Op<&CsrMatrix<T>>,
Op<&CsrMatrix<T>>,
) -> Result<(), OperationError>,
{
use Op::{NoOp, Transpose};
// Currently we handle transposition by explicitly precomputing transposed matrices
// and calling the operation again without transposition
// TODO: At least use workspaces to allow control of allocations. Maybe
// consider implementing certain patterns (like A^T * B) explicitly
let a_ref: &CsrMatrix<T> = a.inner_ref();
let b_ref: &CsrMatrix<T> = b.inner_ref();
let (a, b) = {
use Cow::*;
match (&a, &b) {
(NoOp(_), NoOp(_)) => unreachable!(),
(Transpose(ref a), NoOp(_)) => (Owned(a.transpose()), Borrowed(b_ref)),
(NoOp(_), Transpose(ref b)) => (Borrowed(a_ref), Owned(b.transpose())),
(Transpose(ref a), Transpose(ref b)) => {
(Owned(a.transpose()), Owned(b.transpose()))
}
(Transpose(a), NoOp(_)) => (Owned(a.transpose()), Borrowed(b_ref)),
(NoOp(_), Transpose(b)) => (Borrowed(a_ref), Owned(b.transpose())),
(Transpose(a), Transpose(b)) => (Owned(a.transpose()), Owned(b.transpose())),
}
};
spmm_csr_prealloc(beta, c, alpha, NoOp(a.as_ref()), NoOp(b.as_ref()))
}
}
spmm_kernel(beta, c, alpha, NoOp(a.as_ref()), NoOp(b.as_ref()))
}

View File

@ -125,18 +125,22 @@ fn iterate_union<'a>(
) -> impl Iterator<Item = usize> + 'a {
iter::from_fn(move || {
if let (Some(a_item), Some(b_item)) = (sorted_a.first(), sorted_b.first()) {
let item = if a_item < b_item {
let item = match a_item.cmp(b_item) {
std::cmp::Ordering::Less => {
sorted_a = &sorted_a[1..];
a_item
} else if b_item < a_item {
}
std::cmp::Ordering::Greater => {
sorted_b = &sorted_b[1..];
b_item
} else {
}
std::cmp::Ordering::Equal => {
// Both lists contain the same element, advance both slices to avoid
// duplicate entries in the result
sorted_a = &sorted_a[1..];
sorted_b = &sorted_b[1..];
a_item
}
};
Some(*item)
} else if let Some(a_item) = sorted_a.first() {

View File

@ -80,7 +80,7 @@ impl SparsityPattern {
#[inline]
#[must_use]
pub fn major_dim(&self) -> usize {
assert!(self.major_offsets.len() > 0);
assert!(!self.major_offsets.is_empty());
self.major_offsets.len() - 1
}
@ -162,7 +162,7 @@ impl SparsityPattern {
// We test for in-bounds, uniqueness and monotonicity at the same time
// to ensure that we only visit each minor index once
let mut iter = minor_indices.iter();
let mut prev = None;
let mut prev: Option<usize> = None;
while let Some(next) = iter.next().copied() {
if next >= minor_dim {
@ -170,10 +170,10 @@ impl SparsityPattern {
}
if let Some(prev) = prev {
if prev > next {
return Err(NonmonotonicMinorIndices);
} else if prev == next {
return Err(DuplicateEntry);
match prev.cmp(&next) {
std::cmp::Ordering::Greater => return Err(NonmonotonicMinorIndices),
std::cmp::Ordering::Equal => return Err(DuplicateEntry),
std::cmp::Ordering::Less => {}
}
}
prev = Some(next);
@ -195,6 +195,14 @@ impl SparsityPattern {
///
/// Panics if the number of major offsets is not exactly one greater than the major dimension
/// or if major offsets do not start with 0 and end with the number of minor indices.
///
/// # Safety
///
/// Assumes that the major offsets and indices adhere to the requirements of being a valid
/// sparsity pattern.
/// Specifically, that major offsets is monotonically increasing, and
/// `major_offsets[i]..major_offsets[i+1]` refers to a major lane in the sparsity pattern,
/// and `minor_indices[major_offsets[i]..major_offsets[i+1]]` is monotonically increasing.
pub unsafe fn from_offset_and_indices_unchecked(
major_dim: usize,
minor_dim: usize,
@ -291,6 +299,16 @@ impl SparsityPattern {
}
}
impl Default for SparsityPattern {
fn default() -> Self {
Self {
major_offsets: vec![0],
minor_indices: vec![],
minor_dim: 0,
}
}
}
/// Error type for `SparsityPattern` format errors.
#[non_exhaustive]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]

View File

@ -87,6 +87,40 @@ fn coo_construction_for_valid_data() {
}
}
#[test]
fn coo_triplets_iter_mut() {
// Arbitrary matrix, with duplicates
let i = vec![0, 1, 0, 0, 0, 0, 2, 1];
let j = vec![0, 2, 0, 1, 0, 3, 3, 2];
let v = vec![2, 3, 4, 7, 1, 3, 1, 5];
let mut coo =
CooMatrix::<i32>::try_from_triplets(3, 5, i.clone(), j.clone(), v.clone()).unwrap();
let actual_triplets: Vec<_> = coo.triplet_iter_mut().map(|(i, j, v)| (i, j, *v)).collect();
let expected_triplets: Vec<_> = i
.iter()
.zip(&j)
.zip(&v)
.map(|((i, j), v)| (*i, *j, *v))
.collect();
assert_eq!(expected_triplets, actual_triplets);
for (_i, _j, v) in coo.triplet_iter_mut() {
*v += *v;
}
let actual_triplets: Vec<_> = coo.triplet_iter_mut().map(|(i, j, v)| (i, j, *v)).collect();
let v = vec![4, 6, 8, 14, 2, 6, 2, 10];
let expected_triplets: Vec<_> = i
.iter()
.zip(&j)
.zip(&v)
.map(|((i, j), v)| (*i, *j, *v))
.collect();
assert_eq!(expected_triplets, actual_triplets);
}
#[test]
fn coo_try_from_triplets_reports_out_of_bounds_indices() {
{
@ -150,6 +184,31 @@ fn coo_try_from_triplets_reports_out_of_bounds_indices() {
}
}
#[test]
fn coo_try_from_triplets_iter() {
// Check that try_from_triplets_iter panics when the triplet vectors have different lengths
macro_rules! assert_errs {
($result:expr) => {
assert!(matches!(
$result.unwrap_err().kind(),
SparseFormatErrorKind::IndexOutOfBounds
))
};
}
assert_errs!(CooMatrix::<f32>::try_from_triplets_iter(
3,
5,
vec![(0, 6, 3.0)].into_iter(),
));
assert!(CooMatrix::<f32>::try_from_triplets_iter(
3,
5,
vec![(0, 3, 3.0), (1, 2, 2.0), (0, 3, 1.0),].into_iter(),
)
.is_ok());
}
#[test]
fn coo_try_from_triplets_panics_on_mismatched_vectors() {
// Check that try_from_triplets panics when the triplet vectors have different lengths
@ -226,6 +285,29 @@ fn coo_push_valid_entries() {
);
}
#[test]
fn coo_clear_triplets_valid_entries() {
let mut coo = CooMatrix::new(3, 3);
coo.push(0, 0, 1);
coo.push(0, 0, 2);
coo.push(2, 2, 3);
assert_eq!(
coo.triplet_iter().collect::<Vec<_>>(),
vec![(0, 0, &1), (0, 0, &2), (2, 2, &3)]
);
coo.clear_triplets();
assert_eq!(coo.triplet_iter().collect::<Vec<_>>(), vec![]);
// making sure everyhting works after clearing
coo.push(0, 0, 1);
coo.push(0, 0, 2);
coo.push(2, 2, 3);
assert_eq!(
coo.triplet_iter().collect::<Vec<_>>(),
vec![(0, 0, &1), (0, 0, &2), (2, 2, &3)]
);
}
#[test]
fn coo_push_out_of_bounds_entries() {
{
@ -291,8 +373,8 @@ fn coo_push_matrix_valid_entries() {
// Works with sliced
{
let source = nalgebra::SMatrix::<i32, 2, 2>::new(6, 7, 8, 9);
let sliced = source.fixed_slice::<2, 1>(0, 0);
coo.push_matrix(1, 0, &sliced);
let view = source.fixed_view::<2, 1>(0, 0);
coo.push_matrix(1, 0, &view);
assert_eq!(
coo.triplet_iter().collect::<Vec<_>>(),

View File

@ -12,6 +12,18 @@ use crate::common::csc_strategy;
use std::collections::HashSet;
#[test]
fn csc_matrix_default() {
let matrix: CscMatrix<f32> = CscMatrix::default();
assert_eq!(matrix.nrows(), 0);
assert_eq!(matrix.ncols(), 0);
assert_eq!(matrix.nnz(), 0);
assert_eq!(matrix.values(), &[]);
assert!(matrix.get_entry(0, 0).is_none());
}
#[test]
fn csc_matrix_valid_data() {
// Construct matrix from valid data and check that selected methods return results

View File

@ -12,6 +12,18 @@ use crate::common::csr_strategy;
use std::collections::HashSet;
#[test]
fn csr_matrix_default() {
let matrix: CsrMatrix<f32> = CsrMatrix::default();
assert_eq!(matrix.nrows(), 0);
assert_eq!(matrix.ncols(), 0);
assert_eq!(matrix.nnz(), 0);
assert_eq!(matrix.values(), &[]);
assert!(matrix.get_entry(0, 0).is_none());
}
#[test]
fn csr_matrix_valid_data() {
// Construct matrix from valid data and check that selected methods return results

View File

@ -1,12 +1,21 @@
use matrixcompare::assert_matrix_eq;
use nalgebra::dmatrix;
use nalgebra::matrix;
use nalgebra::Complex;
use nalgebra_sparse::io::load_coo_from_matrix_market_str;
use nalgebra_sparse::io::{
load_coo_from_matrix_market_file, load_coo_from_matrix_market_str, save_to_matrix_market_file,
save_to_matrix_market_str,
};
use nalgebra_sparse::proptest::coo_no_duplicates;
use nalgebra_sparse::CooMatrix;
use proptest::prelude::*;
use tempfile::tempdir;
type C64 = Complex<f64>;
type C32 = Complex<f32>;
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_real_general_empty() {
fn test_matrixmarket_load_sparse_real_general_empty() {
// Test several valid zero-shapes of a sparse matrix
let shapes = vec![ (0, 0), (1, 0), (0, 1) ];
let strings: Vec<String> = shapes
@ -24,7 +33,7 @@ fn test_matrixmarket_sparse_real_general_empty() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_real_general_empty() {
fn test_matrixmarket_load_dense_real_general_empty() {
// Test several valid zero-shapes of a dense matrix
let shapes = vec![ (0, 0), (1, 0), (0, 1) ];
let strings: Vec<String> = shapes
@ -42,7 +51,7 @@ fn test_matrixmarket_dense_real_general_empty() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_real_general() {
fn test_matrixmarket_load_sparse_real_general() {
let file_str = r#"
%%MatrixMarket matrix CoOrdinate real general
% This is also an example of free-format features.
@ -89,7 +98,7 @@ fn test_matrixmarket_sparse_real_general() {
5 5 1.200e+01
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
1.0, 0.0, 0.0, 6.0, 0.0;
0.0, 10.5, 0.0, 0.0, 0.0;
0.0, 0.0, 0.015, 0.0, 0.0;
@ -101,7 +110,7 @@ fn test_matrixmarket_sparse_real_general() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_int_symmetric() {
fn test_matrixmarket_load_sparse_int_symmetric() {
let file_str = r#"
%%MatrixMarket matrix coordinate integer symmetric
%
@ -117,7 +126,7 @@ fn test_matrixmarket_sparse_int_symmetric() {
5 5 55
"#;
let sparse_mat = load_coo_from_matrix_market_str::<i128>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
11, 0, 0, 0, -15;
0, 22, 23, 24, 0;
0, 23, 33, 0, 35;
@ -129,7 +138,7 @@ fn test_matrixmarket_sparse_int_symmetric() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_complex_hermitian() {
fn test_matrixmarket_load_sparse_complex_hermitian() {
let file_str = r#"
%%MatrixMarket matrix coordinate complex hermitian
%
@ -144,19 +153,19 @@ fn test_matrixmarket_sparse_complex_hermitian() {
"#;
let sparse_mat = load_coo_from_matrix_market_str::<Complex<f64>>(file_str).unwrap();
let expected = dmatrix![
Complex::<f64>{re:1.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0},Complex::<f64>{re:0.0,im:0.0};
Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:10.5,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:250.5,im:-22.22},Complex::<f64>{re:0.0,im:0.0};
Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.015,im:0.0}, Complex::<f64>{re:0.0,im:0.0},Complex::<f64>{re:0.0,im:0.0};
Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:250.5,im:22.22}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:-280.0,im:0.0},Complex::<f64>{re:0.0,im:-33.32};
Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:0.0}, Complex::<f64>{re:0.0,im:33.32},Complex::<f64>{re:12.0,im:0.0};
let expected = matrix![
C64{re:1.0,im:0.0}, C64{re:0.0,im:0.0}, C64{re:0.0,im:0.0}, C64{re:0.0,im:0.0},C64{re:0.0,im:0.0};
C64{re:0.0,im:0.0}, C64{re:10.5,im:0.0}, C64{re:0.0,im:0.0}, C64{re:250.5,im:-22.22},C64{re:0.0,im:0.0};
C64{re:0.0,im:0.0}, C64{re:0.0,im:0.0}, C64{re:0.015,im:0.0}, C64{re:0.0,im:0.0},C64{re:0.0,im:0.0};
C64{re:0.0,im:0.0}, C64{re:250.5,im:22.22}, C64{re:0.0,im:0.0}, C64{re:-280.0,im:0.0},C64{re:0.0,im:-33.32};
C64{re:0.0,im:0.0}, C64{re:0.0,im:0.0}, C64{re:0.0,im:0.0}, C64{re:0.0,im:33.32},C64{re:12.0,im:0.0};
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_real_skew() {
fn test_matrixmarket_load_sparse_real_skew() {
let file_str = r#"
%%MatrixMarket matrix coordinate real skew-symmetric
%
@ -167,7 +176,7 @@ fn test_matrixmarket_sparse_real_skew() {
5 3 -35.0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f64>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
0.0, 0.0, 0.0, 0.0, 15.0;
0.0, 0.0, 23.0, 24.0, 0.0;
0.0, -23.0, 0.0, 0.0, 35.0;
@ -179,7 +188,7 @@ fn test_matrixmarket_sparse_real_skew() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_sparse_pattern_general() {
fn test_matrixmarket_load_sparse_pattern_general() {
let file_str = r#"
%%MatrixMarket matrix coordinate pattern general
%
@ -198,10 +207,10 @@ fn test_matrixmarket_sparse_pattern_general() {
let pattern_matrix = load_coo_from_matrix_market_str::<()>(file_str).unwrap();
let nrows = pattern_matrix.nrows();
let ncols = pattern_matrix.ncols();
let (row_idx, col_idx, val) = pattern_matrix.disassemble();
let (row_idx, col_idx, val) = pattern_matrix.clone().disassemble();
let values = vec![1; val.len()];
let sparse_mat = CooMatrix::try_from_triplets(nrows, ncols, row_idx, col_idx, values).unwrap();
let expected = dmatrix![
let expected = matrix![
1, 0, 0, 0, 1;
0, 0, 1, 1, 0;
0, 1, 0, 0, 1;
@ -213,7 +222,7 @@ fn test_matrixmarket_sparse_pattern_general() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_real_general() {
fn test_matrixmarket_load_dense_real_general() {
let file_str = r#"
%%MatrixMarket matrix array real general
%
@ -233,7 +242,7 @@ fn test_matrixmarket_dense_real_general() {
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
1.0, 5.0, 9.0;
2.0, 6.0, 10.0;
3.0, 7.0, 11.0;
@ -244,7 +253,7 @@ fn test_matrixmarket_dense_real_general() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_real_symmetric() {
fn test_matrixmarket_load_dense_real_symmetric() {
let file_str = r#"
%%MatrixMarket matrix array real symmetric
%
@ -262,7 +271,7 @@ fn test_matrixmarket_dense_real_symmetric() {
"#;
let sparse_mat = load_coo_from_matrix_market_str::<f32>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
1.0, 2.0, 3.0, 4.0;
2.0, 5.0, 6.0, 7.0;
3.0, 6.0, 8.0, 9.0;
@ -273,7 +282,7 @@ fn test_matrixmarket_dense_real_symmetric() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_complex_hermitian() {
fn test_matrixmarket_load_dense_complex_hermitian() {
let file_str = r#"
%%MatrixMarket matrix array complex hermitian
%
@ -290,19 +299,19 @@ fn test_matrixmarket_dense_complex_hermitian() {
10.0 0.0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<Complex<f64>>(file_str).unwrap();
let expected = dmatrix![
Complex::<f64>{re:1.0,im:0.0}, Complex::<f64>{re:2.0,im:-2.0} ,Complex::<f64>{re:3.0,im:-3.0} ,Complex::<f64>{re:4.0,im:-4.0};
Complex::<f64>{re:2.0,im:2.0}, Complex::<f64>{re:5.0,im:0.0} ,Complex::<f64>{re:6.0,im:-6.0} ,Complex::<f64>{re:7.0,im:-7.0};
Complex::<f64>{re:3.0,im:3.0}, Complex::<f64>{re:6.0,im:6.0} ,Complex::<f64>{re:8.0,im:0.0} ,Complex::<f64>{re:9.0,im:-9.0};
Complex::<f64>{re:4.0,im:4.0}, Complex::<f64>{re:7.0,im:7.0} ,Complex::<f64>{re:9.0,im:9.0} ,Complex::<f64>{re:10.0,im:0.0};
let sparse_mat = load_coo_from_matrix_market_str::<C64>(file_str).unwrap();
let expected = matrix![
C64{re:1.0,im:0.0}, C64{re:2.0,im:-2.0} ,C64{re:3.0,im:-3.0} ,C64{re:4.0,im:-4.0};
C64{re:2.0,im:2.0}, C64{re:5.0,im:0.0} ,C64{re:6.0,im:-6.0} ,C64{re:7.0,im:-7.0};
C64{re:3.0,im:3.0}, C64{re:6.0,im:6.0} ,C64{re:8.0,im:0.0} ,C64{re:9.0,im:-9.0};
C64{re:4.0,im:4.0}, C64{re:7.0,im:7.0} ,C64{re:9.0,im:9.0} ,C64{re:10.0,im:0.0};
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_int_skew() {
fn test_matrixmarket_load_dense_int_skew() {
let file_str = r#"
%%MatrixMarket matrix array integer skew-symmetric
%
@ -315,7 +324,7 @@ fn test_matrixmarket_dense_int_skew() {
6
"#;
let sparse_mat = load_coo_from_matrix_market_str::<i32>(file_str).unwrap();
let expected = dmatrix![
let expected = matrix![
0,-1,-2,-3;
1, 0,-4,-5;
2, 4, 0,-6;
@ -326,7 +335,7 @@ fn test_matrixmarket_dense_int_skew() {
#[test]
#[rustfmt::skip]
fn test_matrixmarket_dense_complex_general() {
fn test_matrixmarket_load_dense_complex_general() {
let file_str = r#"
%%MatrixMarket matrix array complex general
%
@ -336,10 +345,124 @@ fn test_matrixmarket_dense_complex_general() {
1 0
1 0
"#;
let sparse_mat = load_coo_from_matrix_market_str::<Complex<f32>>(file_str).unwrap();
let expected = dmatrix![
Complex::<f32>{re:1.0,im:0.0},Complex::<f32>{re:1.0,im:0.0};
Complex::<f32>{re:1.0,im:0.0},Complex::<f32>{re:1.0,im:0.0};
let sparse_mat = load_coo_from_matrix_market_str::<C32>(file_str).unwrap();
let expected = matrix![
C32{re:1.0,im:0.0},C32{re:1.0,im:0.0};
C32{re:1.0,im:0.0},C32{re:1.0,im:0.0};
];
assert_matrix_eq!(sparse_mat, expected);
}
#[test]
#[rustfmt::skip]
fn test_matrixmarket_write_real(){
let dense_matrix = matrix![
1.0, 2.0, 3.0;
2.0, 0.0, 3.0;
];
let row_indices = vec![0,1,0,0,1];
let col_indices = vec![0,0,1,2,2];
let values = vec![1.0,2.0,2.0,3.0,3.0];
let coo_matrix = CooMatrix::try_from_triplets(2, 3, row_indices, col_indices, values).unwrap();
assert_matrix_eq!(dense_matrix,coo_matrix);
let expected = r#"%%matrixmarket matrix coordinate real general
% matrixmarket file generated by nalgebra-sparse.
2 3 5
1 1 1
2 1 2
1 2 2
1 3 3
2 3 3
"#;
let matrixmarket_str = save_to_matrix_market_str(&coo_matrix);
assert_eq!(matrixmarket_str,expected);
}
#[test]
fn test_matrixmarket_write_int() {
let dense_matrix = matrix![
1,2,3;
2,0,3;
];
let row_indices = vec![0, 1, 0, 0, 1];
let col_indices = vec![0, 0, 1, 2, 2];
let values = vec![1, 2, 2, 3, 3];
let coo_matrix = CooMatrix::try_from_triplets(2, 3, row_indices, col_indices, values).unwrap();
assert_matrix_eq!(dense_matrix, coo_matrix);
let expected = r#"%%matrixmarket matrix coordinate integer general
% matrixmarket file generated by nalgebra-sparse.
2 3 5
1 1 1
2 1 2
1 2 2
1 3 3
2 3 3
"#;
let matrixmarket_str = save_to_matrix_market_str(&coo_matrix);
assert_eq!(matrixmarket_str, expected);
}
#[test]
fn test_matrixmarket_write_pattern() {
let row_indices = vec![0, 1, 0, 0, 1];
let col_indices = vec![0, 0, 1, 2, 2];
let values = vec![(), (), (), (), ()];
let coo_matrix = CooMatrix::try_from_triplets(2, 3, row_indices, col_indices, values).unwrap();
let expected = r#"%%matrixmarket matrix coordinate pattern general
% matrixmarket file generated by nalgebra-sparse.
2 3 5
1 1
2 1
1 2
1 3
2 3
"#;
let matrixmarket_str = save_to_matrix_market_str(&coo_matrix);
assert_eq!(matrixmarket_str, expected);
}
#[test]
fn test_matrixmarket_write_complex() {
let row_indices = vec![0, 1, 0, 0, 1];
let col_indices = vec![0, 0, 1, 2, 2];
let values = vec![
C64 { re: 1.0, im: 2.0 },
C64 { re: 2.0, im: 3.0 },
C64 { re: 3.0, im: 4.0 },
C64 { re: 4.0, im: 5.0 },
C64 { re: 5.0, im: 6.0 },
];
let coo_matrix = CooMatrix::try_from_triplets(2, 3, row_indices, col_indices, values).unwrap();
let expected = r#"%%matrixmarket matrix coordinate complex general
% matrixmarket file generated by nalgebra-sparse.
2 3 5
1 1 1 2
2 1 2 3
1 2 3 4
1 3 4 5
2 3 5 6
"#;
let matrixmarket_str = save_to_matrix_market_str(&coo_matrix);
assert_eq!(matrixmarket_str, expected);
}
proptest! {
#[test]
fn coo_matrix_market_roundtrip_str(coo in coo_no_duplicates(-10 ..= 10, 0 ..= 10, 0..= 10, 100)) {
let generated_matrixmarket_string = save_to_matrix_market_str(&coo);
let generated_matrix = load_coo_from_matrix_market_str(&generated_matrixmarket_string).unwrap();
assert_matrix_eq!(generated_matrix, coo);
}
}
proptest! {
#[test]
fn coo_matrix_market_roundtrip_file(coo in coo_no_duplicates(-10 ..= 10, 0 ..= 10, 0..= 10, 100)) {
let temp_dir = tempdir().expect("Unable to create temporary directory");
let file_path = temp_dir.path().join("temp.mtx");
save_to_matrix_market_file(&coo,&file_path).unwrap();
let generated_matrix = load_coo_from_matrix_market_file(file_path).unwrap();
assert_matrix_eq!(generated_matrix, coo);
temp_dir.close().expect("Unable to delete temporary directory");
}
}

View File

@ -6,14 +6,15 @@ use nalgebra_sparse::csc::CscMatrix;
use nalgebra_sparse::csr::CsrMatrix;
use nalgebra_sparse::ops::serial::{
spadd_csc_prealloc, spadd_csr_prealloc, spadd_pattern, spmm_csc_dense, spmm_csc_prealloc,
spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc, spsolve_csc_lower_triangular,
spmm_csc_prealloc_unchecked, spmm_csr_dense, spmm_csr_pattern, spmm_csr_prealloc,
spmm_csr_prealloc_unchecked, spsolve_csc_lower_triangular,
};
use nalgebra_sparse::ops::Op;
use nalgebra_sparse::pattern::SparsityPattern;
use nalgebra_sparse::proptest::{csc, csr, sparsity_pattern};
use nalgebra::proptest::{matrix, vector};
use nalgebra::{DMatrix, DMatrixSlice, DMatrixSliceMut, Scalar};
use nalgebra::{DMatrix, DMatrixView, DMatrixViewMut, Scalar};
use proptest::prelude::*;
@ -332,10 +333,10 @@ fn csc_square_with_non_zero_diagonals() -> impl Strategy<Value = CscMatrix<f64>>
/// Helper function to help us call dense GEMM with our `Op` type
fn dense_gemm<'a>(
beta: i32,
c: impl Into<DMatrixSliceMut<'a, i32>>,
c: impl Into<DMatrixViewMut<'a, i32>>,
alpha: i32,
a: Op<impl Into<DMatrixSlice<'a, i32>>>,
b: Op<impl Into<DMatrixSlice<'a, i32>>>,
a: Op<impl Into<DMatrixView<'a, i32>>>,
b: Op<impl Into<DMatrixView<'a, i32>>>,
) {
let mut c = c.into();
let a = a.convert();
@ -543,6 +544,29 @@ proptest! {
prop_assert_eq!(&c_pattern, c_csr.pattern());
}
#[test]
fn spmm_csr_prealloc_unchecked_test(SpmmCsrArgs { c, beta, alpha, a, b }
in spmm_csr_prealloc_args_strategy()
) {
// Test that we get the expected result by comparing to an equivalent dense operation
// (here we give in the C matrix, so the sparsity pattern is essentially fixed)
let mut c_sparse = c.clone();
spmm_csr_prealloc_unchecked(beta, &mut c_sparse, alpha, a.as_ref(), b.as_ref()).unwrap();
let mut c_dense = DMatrix::from(&c);
let op_a_dense = match a {
Op::NoOp(ref a) => DMatrix::from(a),
Op::Transpose(ref a) => DMatrix::from(a).transpose(),
};
let op_b_dense = match b {
Op::NoOp(ref b) => DMatrix::from(b),
Op::Transpose(ref b) => DMatrix::from(b).transpose(),
};
c_dense = beta * c_dense + alpha * &op_a_dense * op_b_dense;
prop_assert_eq!(&DMatrix::from(&c_sparse), &c_dense);
}
#[test]
fn spmm_csr_prealloc_test(SpmmCsrArgs { c, beta, alpha, a, b }
in spmm_csr_prealloc_args_strategy()
@ -705,6 +729,29 @@ proptest! {
prop_assert_eq!(&DMatrix::from(&c_sparse), &c_dense);
}
#[test]
fn spmm_csc_prealloc_unchecked_test(SpmmCscArgs { c, beta, alpha, a, b }
in spmm_csc_prealloc_args_strategy()
) {
// Test that we get the expected result by comparing to an equivalent dense operation
// (here we give in the C matrix, so the sparsity pattern is essentially fixed)
let mut c_sparse = c.clone();
spmm_csc_prealloc_unchecked(beta, &mut c_sparse, alpha, a.as_ref(), b.as_ref()).unwrap();
let mut c_dense = DMatrix::from(&c);
let op_a_dense = match a {
Op::NoOp(ref a) => DMatrix::from(a),
Op::Transpose(ref a) => DMatrix::from(a).transpose(),
};
let op_b_dense = match b {
Op::NoOp(ref b) => DMatrix::from(b),
Op::Transpose(ref b) => DMatrix::from(b).transpose(),
};
c_dense = beta * c_dense + alpha * &op_a_dense * op_b_dense;
prop_assert_eq!(&DMatrix::from(&c_sparse), &c_dense);
}
#[test]
fn spmm_csc_prealloc_panics_on_dim_mismatch(
(alpha, beta, c, a, b)

View File

@ -1,5 +1,19 @@
use nalgebra_sparse::pattern::{SparsityPattern, SparsityPatternFormatError};
#[test]
fn sparsity_pattern_default() {
// Check that the pattern created with `Default::default()` is equivalent to a zero-sized pattern.
let pattern = SparsityPattern::default();
let zero = SparsityPattern::zeros(0, 0);
assert_eq!(pattern.major_dim(), zero.major_dim());
assert_eq!(pattern.minor_dim(), zero.minor_dim());
assert_eq!(pattern.major_offsets(), zero.major_offsets());
assert_eq!(pattern.minor_indices(), zero.minor_indices());
assert_eq!(pattern.nnz(), 0);
}
#[test]
fn sparsity_pattern_valid_data() {
// Construct pattern from valid data and check that selected methods return results

View File

@ -1,5 +1,5 @@
#[cfg(any(feature = "alloc", feature = "std"))]
use crate::base::dimension::Dynamic;
use crate::base::dimension::Dyn;
use crate::base::dimension::{U1, U2, U3, U4, U5, U6};
use crate::base::storage::Owned;
#[cfg(any(feature = "std", feature = "alloc"))]
@ -48,69 +48,69 @@ pub type SMatrix<T, const R: usize, const C: usize> =
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type DMatrix<T> = Matrix<T, Dynamic, Dynamic, VecStorage<T, Dynamic, Dynamic>>;
pub type DMatrix<T> = Matrix<T, Dyn, Dyn, VecStorage<T, Dyn, Dyn>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 1 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx1<T> = Matrix<T, Dynamic, U1, VecStorage<T, Dynamic, U1>>;
pub type MatrixXx1<T> = Matrix<T, Dyn, U1, VecStorage<T, Dyn, U1>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 2 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx2<T> = Matrix<T, Dynamic, U2, VecStorage<T, Dynamic, U2>>;
pub type MatrixXx2<T> = Matrix<T, Dyn, U2, VecStorage<T, Dyn, U2>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 3 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx3<T> = Matrix<T, Dynamic, U3, VecStorage<T, Dynamic, U3>>;
pub type MatrixXx3<T> = Matrix<T, Dyn, U3, VecStorage<T, Dyn, U3>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 4 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx4<T> = Matrix<T, Dynamic, U4, VecStorage<T, Dynamic, U4>>;
pub type MatrixXx4<T> = Matrix<T, Dyn, U4, VecStorage<T, Dyn, U4>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 5 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx5<T> = Matrix<T, Dynamic, U5, VecStorage<T, Dynamic, U5>>;
pub type MatrixXx5<T> = Matrix<T, Dyn, U5, VecStorage<T, Dyn, U5>>;
/// A heap-allocated, column-major, matrix with a dynamic number of rows and 6 columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type MatrixXx6<T> = Matrix<T, Dynamic, U6, VecStorage<T, Dynamic, U6>>;
pub type MatrixXx6<T> = Matrix<T, Dyn, U6, VecStorage<T, Dyn, U6>>;
/// A heap-allocated, row-major, matrix with 1 rows and a dynamic number of columns.
/// A heap-allocated, column-major, matrix with 1 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix1xX<T> = Matrix<T, U1, Dynamic, VecStorage<T, U1, Dynamic>>;
/// A heap-allocated, row-major, matrix with 2 rows and a dynamic number of columns.
pub type Matrix1xX<T> = Matrix<T, U1, Dyn, VecStorage<T, U1, Dyn>>;
/// A heap-allocated, column-major, matrix with 2 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix2xX<T> = Matrix<T, U2, Dynamic, VecStorage<T, U2, Dynamic>>;
/// A heap-allocated, row-major, matrix with 3 rows and a dynamic number of columns.
pub type Matrix2xX<T> = Matrix<T, U2, Dyn, VecStorage<T, U2, Dyn>>;
/// A heap-allocated, column-major, matrix with 3 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix3xX<T> = Matrix<T, U3, Dynamic, VecStorage<T, U3, Dynamic>>;
/// A heap-allocated, row-major, matrix with 4 rows and a dynamic number of columns.
pub type Matrix3xX<T> = Matrix<T, U3, Dyn, VecStorage<T, U3, Dyn>>;
/// A heap-allocated, column-major, matrix with 4 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix4xX<T> = Matrix<T, U4, Dynamic, VecStorage<T, U4, Dynamic>>;
/// A heap-allocated, row-major, matrix with 5 rows and a dynamic number of columns.
pub type Matrix4xX<T> = Matrix<T, U4, Dyn, VecStorage<T, U4, Dyn>>;
/// A heap-allocated, column-major, matrix with 5 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix5xX<T> = Matrix<T, U5, Dynamic, VecStorage<T, U5, Dynamic>>;
/// A heap-allocated, row-major, matrix with 6 rows and a dynamic number of columns.
pub type Matrix5xX<T> = Matrix<T, U5, Dyn, VecStorage<T, U5, Dyn>>;
/// A heap-allocated, column-major, matrix with 6 rows and a dynamic number of columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[cfg(any(feature = "std", feature = "alloc"))]
pub type Matrix6xX<T> = Matrix<T, U6, Dynamic, VecStorage<T, U6, Dynamic>>;
pub type Matrix6xX<T> = Matrix<T, U6, Dyn, VecStorage<T, U6, Dyn>>;
/// A stack-allocated, column-major, 1x1 square matrix.
///
@ -276,7 +276,7 @@ pub type Matrix6x5<T> = Matrix<T, U6, U5, ArrayStorage<T, 6, 5>>;
*/
/// A dynamically sized column vector.
#[cfg(any(feature = "std", feature = "alloc"))]
pub type DVector<T> = Matrix<T, Dynamic, U1, VecStorage<T, Dynamic, U1>>;
pub type DVector<T> = Matrix<T, Dyn, U1, VecStorage<T, Dyn, U1>>;
/// An owned D-dimensional column vector.
pub type OVector<T, D> = Matrix<T, D, U1, Owned<T, D, U1>>;
@ -316,7 +316,7 @@ pub type Vector6<T> = Matrix<T, U6, U1, ArrayStorage<T, 6, 1>>;
*/
/// A dynamically sized row vector.
#[cfg(any(feature = "std", feature = "alloc"))]
pub type RowDVector<T> = Matrix<T, U1, Dynamic, VecStorage<T, U1, Dynamic>>;
pub type RowDVector<T> = Matrix<T, U1, Dyn, VecStorage<T, U1, Dyn>>;
/// An owned D-dimensional row vector.
pub type RowOVector<T, D> = Matrix<T, U1, D, Owned<T, U1, D>>;

View File

@ -1,6 +1,7 @@
use crate::base::dimension::{Dynamic, U1, U2, U3, U4, U5, U6};
use crate::base::matrix_slice::{SliceStorage, SliceStorageMut};
use crate::base::dimension::{Dyn, U1, U2, U3, U4, U5, U6};
use crate::base::matrix_view::{ViewStorage, ViewStorageMut};
use crate::base::{Const, Matrix};
use crate::slice_deprecation_note;
/*
*
@ -13,286 +14,345 @@ use crate::base::{Const, Matrix};
/// A column-major matrix slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(SMatrixView)]
pub type SMatrixSlice<'a, T, const R: usize, const C: usize> =
Matrix<T, Const<R>, Const<C>, SliceStorage<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
Matrix<T, Const<R>, Const<C>, ViewStorage<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
/// A column-major matrix slice dynamic numbers of rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixSlice<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, Dynamic, SliceStorage<'a, T, Dynamic, Dynamic, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(DMatrixView)]
pub type DMatrixSlice<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, Dyn, ViewStorage<'a, T, Dyn, Dyn, RStride, CStride>>;
/// A column-major 1x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1)]
pub type MatrixSlice1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, SliceStorage<'a, T, U1, U1, RStride, CStride>>;
Matrix<T, U1, U1, ViewStorage<'a, T, U1, U1, RStride, CStride>>;
/// A column-major 2x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2)]
pub type MatrixSlice2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U2, SliceStorage<'a, T, U2, U2, RStride, CStride>>;
Matrix<T, U2, U2, ViewStorage<'a, T, U2, U2, RStride, CStride>>;
/// A column-major 3x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3)]
pub type MatrixSlice3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U3, SliceStorage<'a, T, U3, U3, RStride, CStride>>;
Matrix<T, U3, U3, ViewStorage<'a, T, U3, U3, RStride, CStride>>;
/// A column-major 4x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4)]
pub type MatrixSlice4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U4, SliceStorage<'a, T, U4, U4, RStride, CStride>>;
Matrix<T, U4, U4, ViewStorage<'a, T, U4, U4, RStride, CStride>>;
/// A column-major 5x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5)]
pub type MatrixSlice5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U5, SliceStorage<'a, T, U5, U5, RStride, CStride>>;
Matrix<T, U5, U5, ViewStorage<'a, T, U5, U5, RStride, CStride>>;
/// A column-major 6x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6)]
pub type MatrixSlice6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U6, SliceStorage<'a, T, U6, U6, RStride, CStride>>;
Matrix<T, U6, U6, ViewStorage<'a, T, U6, U6, RStride, CStride>>;
/// A column-major 1x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1x2)]
pub type MatrixSlice1x2<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U2, SliceStorage<'a, T, U1, U2, RStride, CStride>>;
Matrix<T, U1, U2, ViewStorage<'a, T, U1, U2, RStride, CStride>>;
/// A column-major 1x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1x3)]
pub type MatrixSlice1x3<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U3, SliceStorage<'a, T, U1, U3, RStride, CStride>>;
Matrix<T, U1, U3, ViewStorage<'a, T, U1, U3, RStride, CStride>>;
/// A column-major 1x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1x4)]
pub type MatrixSlice1x4<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U4, SliceStorage<'a, T, U1, U4, RStride, CStride>>;
Matrix<T, U1, U4, ViewStorage<'a, T, U1, U4, RStride, CStride>>;
/// A column-major 1x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1x5)]
pub type MatrixSlice1x5<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U5, SliceStorage<'a, T, U1, U5, RStride, CStride>>;
Matrix<T, U1, U5, ViewStorage<'a, T, U1, U5, RStride, CStride>>;
/// A column-major 1x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView1x6)]
pub type MatrixSlice1x6<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U6, SliceStorage<'a, T, U1, U6, RStride, CStride>>;
Matrix<T, U1, U6, ViewStorage<'a, T, U1, U6, RStride, CStride>>;
/// A column-major 2x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2x1)]
pub type MatrixSlice2x1<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, SliceStorage<'a, T, U2, U1, RStride, CStride>>;
Matrix<T, U2, U1, ViewStorage<'a, T, U2, U1, RStride, CStride>>;
/// A column-major 2x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2x3)]
pub type MatrixSlice2x3<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U3, SliceStorage<'a, T, U2, U3, RStride, CStride>>;
Matrix<T, U2, U3, ViewStorage<'a, T, U2, U3, RStride, CStride>>;
/// A column-major 2x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2x4)]
pub type MatrixSlice2x4<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U4, SliceStorage<'a, T, U2, U4, RStride, CStride>>;
Matrix<T, U2, U4, ViewStorage<'a, T, U2, U4, RStride, CStride>>;
/// A column-major 2x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2x5)]
pub type MatrixSlice2x5<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U5, SliceStorage<'a, T, U2, U5, RStride, CStride>>;
Matrix<T, U2, U5, ViewStorage<'a, T, U2, U5, RStride, CStride>>;
/// A column-major 2x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView2x6)]
pub type MatrixSlice2x6<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U6, SliceStorage<'a, T, U2, U6, RStride, CStride>>;
Matrix<T, U2, U6, ViewStorage<'a, T, U2, U6, RStride, CStride>>;
/// A column-major 3x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3x1)]
pub type MatrixSlice3x1<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, SliceStorage<'a, T, U3, U1, RStride, CStride>>;
Matrix<T, U3, U1, ViewStorage<'a, T, U3, U1, RStride, CStride>>;
/// A column-major 3x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3x2)]
pub type MatrixSlice3x2<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U2, SliceStorage<'a, T, U3, U2, RStride, CStride>>;
Matrix<T, U3, U2, ViewStorage<'a, T, U3, U2, RStride, CStride>>;
/// A column-major 3x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3x4)]
pub type MatrixSlice3x4<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U4, SliceStorage<'a, T, U3, U4, RStride, CStride>>;
Matrix<T, U3, U4, ViewStorage<'a, T, U3, U4, RStride, CStride>>;
/// A column-major 3x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3x5)]
pub type MatrixSlice3x5<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U5, SliceStorage<'a, T, U3, U5, RStride, CStride>>;
Matrix<T, U3, U5, ViewStorage<'a, T, U3, U5, RStride, CStride>>;
/// A column-major 3x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView3x6)]
pub type MatrixSlice3x6<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U6, SliceStorage<'a, T, U3, U6, RStride, CStride>>;
Matrix<T, U3, U6, ViewStorage<'a, T, U3, U6, RStride, CStride>>;
/// A column-major 4x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4x1)]
pub type MatrixSlice4x1<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, SliceStorage<'a, T, U4, U1, RStride, CStride>>;
Matrix<T, U4, U1, ViewStorage<'a, T, U4, U1, RStride, CStride>>;
/// A column-major 4x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4x2)]
pub type MatrixSlice4x2<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U2, SliceStorage<'a, T, U4, U2, RStride, CStride>>;
Matrix<T, U4, U2, ViewStorage<'a, T, U4, U2, RStride, CStride>>;
/// A column-major 4x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4x3)]
pub type MatrixSlice4x3<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U3, SliceStorage<'a, T, U4, U3, RStride, CStride>>;
Matrix<T, U4, U3, ViewStorage<'a, T, U4, U3, RStride, CStride>>;
/// A column-major 4x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4x5)]
pub type MatrixSlice4x5<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U5, SliceStorage<'a, T, U4, U5, RStride, CStride>>;
Matrix<T, U4, U5, ViewStorage<'a, T, U4, U5, RStride, CStride>>;
/// A column-major 4x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView4x6)]
pub type MatrixSlice4x6<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U6, SliceStorage<'a, T, U4, U6, RStride, CStride>>;
Matrix<T, U4, U6, ViewStorage<'a, T, U4, U6, RStride, CStride>>;
/// A column-major 5x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5x1)]
pub type MatrixSlice5x1<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, SliceStorage<'a, T, U5, U1, RStride, CStride>>;
Matrix<T, U5, U1, ViewStorage<'a, T, U5, U1, RStride, CStride>>;
/// A column-major 5x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5x2)]
pub type MatrixSlice5x2<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U2, SliceStorage<'a, T, U5, U2, RStride, CStride>>;
Matrix<T, U5, U2, ViewStorage<'a, T, U5, U2, RStride, CStride>>;
/// A column-major 5x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5x3)]
pub type MatrixSlice5x3<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U3, SliceStorage<'a, T, U5, U3, RStride, CStride>>;
Matrix<T, U5, U3, ViewStorage<'a, T, U5, U3, RStride, CStride>>;
/// A column-major 5x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5x4)]
pub type MatrixSlice5x4<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U4, SliceStorage<'a, T, U5, U4, RStride, CStride>>;
Matrix<T, U5, U4, ViewStorage<'a, T, U5, U4, RStride, CStride>>;
/// A column-major 5x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView5x6)]
pub type MatrixSlice5x6<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U6, SliceStorage<'a, T, U5, U6, RStride, CStride>>;
Matrix<T, U5, U6, ViewStorage<'a, T, U5, U6, RStride, CStride>>;
/// A column-major 6x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6x1)]
pub type MatrixSlice6x1<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, SliceStorage<'a, T, U6, U1, RStride, CStride>>;
Matrix<T, U6, U1, ViewStorage<'a, T, U6, U1, RStride, CStride>>;
/// A column-major 6x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6x2)]
pub type MatrixSlice6x2<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U2, SliceStorage<'a, T, U6, U2, RStride, CStride>>;
Matrix<T, U6, U2, ViewStorage<'a, T, U6, U2, RStride, CStride>>;
/// A column-major 6x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6x3)]
pub type MatrixSlice6x3<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U3, SliceStorage<'a, T, U6, U3, RStride, CStride>>;
Matrix<T, U6, U3, ViewStorage<'a, T, U6, U3, RStride, CStride>>;
/// A column-major 6x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6x4)]
pub type MatrixSlice6x4<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U4, SliceStorage<'a, T, U6, U4, RStride, CStride>>;
Matrix<T, U6, U4, ViewStorage<'a, T, U6, U4, RStride, CStride>>;
/// A column-major 6x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixView6x5)]
pub type MatrixSlice6x5<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U5, SliceStorage<'a, T, U6, U5, RStride, CStride>>;
Matrix<T, U6, U5, ViewStorage<'a, T, U6, U5, RStride, CStride>>;
/// A column-major matrix slice with 1 row and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView1xX)]
pub type MatrixSlice1xX<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, Dynamic, SliceStorage<'a, T, U1, Dynamic, RStride, CStride>>;
Matrix<T, U1, Dyn, ViewStorage<'a, T, U1, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 2 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView2xX)]
pub type MatrixSlice2xX<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, Dynamic, SliceStorage<'a, T, U2, Dynamic, RStride, CStride>>;
Matrix<T, U2, Dyn, ViewStorage<'a, T, U2, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 3 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView3xX)]
pub type MatrixSlice3xX<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, Dynamic, SliceStorage<'a, T, U3, Dynamic, RStride, CStride>>;
Matrix<T, U3, Dyn, ViewStorage<'a, T, U3, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 4 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView4xX)]
pub type MatrixSlice4xX<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, Dynamic, SliceStorage<'a, T, U4, Dynamic, RStride, CStride>>;
Matrix<T, U4, Dyn, ViewStorage<'a, T, U4, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 5 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView5xX)]
pub type MatrixSlice5xX<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, Dynamic, SliceStorage<'a, T, U5, Dynamic, RStride, CStride>>;
Matrix<T, U5, Dyn, ViewStorage<'a, T, U5, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 6 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixView6xX)]
pub type MatrixSlice6xX<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, Dynamic, SliceStorage<'a, T, U6, Dynamic, RStride, CStride>>;
Matrix<T, U6, Dyn, ViewStorage<'a, T, U6, Dyn, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 1 column.
pub type MatrixSliceXx1<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U1, SliceStorage<'a, T, Dynamic, U1, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx1)]
pub type MatrixSliceXx1<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorage<'a, T, Dyn, U1, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 2 columns.
pub type MatrixSliceXx2<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U2, SliceStorage<'a, T, Dynamic, U2, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx2)]
pub type MatrixSliceXx2<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U2, ViewStorage<'a, T, Dyn, U2, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 3 columns.
pub type MatrixSliceXx3<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U3, SliceStorage<'a, T, Dynamic, U3, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx3)]
pub type MatrixSliceXx3<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U3, ViewStorage<'a, T, Dyn, U3, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 4 columns.
pub type MatrixSliceXx4<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U4, SliceStorage<'a, T, Dynamic, U4, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx4)]
pub type MatrixSliceXx4<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U4, ViewStorage<'a, T, Dyn, U4, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 5 columns.
pub type MatrixSliceXx5<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U5, SliceStorage<'a, T, Dynamic, U5, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx5)]
pub type MatrixSliceXx5<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U5, ViewStorage<'a, T, Dyn, U5, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 6 columns.
pub type MatrixSliceXx6<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U6, SliceStorage<'a, T, Dynamic, U6, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewXx6)]
pub type MatrixSliceXx6<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U6, ViewStorage<'a, T, Dyn, U6, RStride, CStride>>;
/// A column vector slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView)]
pub type VectorSlice<'a, T, D, RStride = U1, CStride = D> =
Matrix<T, D, U1, SliceStorage<'a, T, D, U1, RStride, CStride>>;
Matrix<T, D, U1, ViewStorage<'a, T, D, U1, RStride, CStride>>;
/// A column vector slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(SVectorView)]
pub type SVectorSlice<'a, T, const D: usize> =
Matrix<T, Const<D>, Const<1>, SliceStorage<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
Matrix<T, Const<D>, Const<1>, ViewStorage<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
/// A column vector slice dynamic numbers of rows and columns.
pub type DVectorSlice<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U1, SliceStorage<'a, T, Dynamic, U1, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(DVectorView)]
pub type DVectorSlice<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorage<'a, T, Dyn, U1, RStride, CStride>>;
/// A 1D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView1)]
pub type VectorSlice1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, SliceStorage<'a, T, U1, U1, RStride, CStride>>;
Matrix<T, U1, U1, ViewStorage<'a, T, U1, U1, RStride, CStride>>;
/// A 2D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView2)]
pub type VectorSlice2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, SliceStorage<'a, T, U2, U1, RStride, CStride>>;
Matrix<T, U2, U1, ViewStorage<'a, T, U2, U1, RStride, CStride>>;
/// A 3D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView3)]
pub type VectorSlice3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, SliceStorage<'a, T, U3, U1, RStride, CStride>>;
Matrix<T, U3, U1, ViewStorage<'a, T, U3, U1, RStride, CStride>>;
/// A 4D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView4)]
pub type VectorSlice4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, SliceStorage<'a, T, U4, U1, RStride, CStride>>;
Matrix<T, U4, U1, ViewStorage<'a, T, U4, U1, RStride, CStride>>;
/// A 5D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView5)]
pub type VectorSlice5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, SliceStorage<'a, T, U5, U1, RStride, CStride>>;
Matrix<T, U5, U1, ViewStorage<'a, T, U5, U1, RStride, CStride>>;
/// A 6D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorView6)]
pub type VectorSlice6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, SliceStorage<'a, T, U6, U1, RStride, CStride>>;
Matrix<T, U6, U1, ViewStorage<'a, T, U6, U1, RStride, CStride>>;
/*
*
@ -304,297 +364,358 @@ pub type VectorSlice6<'a, T, RStride = U1, CStride = U6> =
/// A column-major matrix slice with `R` rows and `C` columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = "Use MatrixViewMut instead, which has an identical definition."]
pub type MatrixSliceMutMN<'a, T, R, C, RStride = U1, CStride = R> =
Matrix<T, R, C, SliceStorageMut<'a, T, R, C, RStride, CStride>>;
Matrix<T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>;
/// A column-major matrix slice with `D` rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = "Use MatrixViewMut instead."]
pub type MatrixSliceMutN<'a, T, D, RStride = U1, CStride = D> =
Matrix<T, D, D, SliceStorageMut<'a, T, D, D, RStride, CStride>>;
Matrix<T, D, D, ViewStorageMut<'a, T, D, D, RStride, CStride>>;
/// A column-major matrix slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(SMatrixViewMut)]
pub type SMatrixSliceMut<'a, T, const R: usize, const C: usize> =
Matrix<T, Const<R>, Const<C>, SliceStorageMut<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
Matrix<T, Const<R>, Const<C>, ViewStorageMut<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
/// A column-major matrix slice dynamic numbers of rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixSliceMut<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, Dynamic, SliceStorageMut<'a, T, Dynamic, Dynamic, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(DMatrixViewMut)]
pub type DMatrixSliceMut<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, Dyn, ViewStorageMut<'a, T, Dyn, Dyn, RStride, CStride>>;
/// A column-major 1x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1)]
pub type MatrixSliceMut1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, SliceStorageMut<'a, T, U1, U1, RStride, CStride>>;
Matrix<T, U1, U1, ViewStorageMut<'a, T, U1, U1, RStride, CStride>>;
/// A column-major 2x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2)]
pub type MatrixSliceMut2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U2, SliceStorageMut<'a, T, U2, U2, RStride, CStride>>;
Matrix<T, U2, U2, ViewStorageMut<'a, T, U2, U2, RStride, CStride>>;
/// A column-major 3x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3)]
pub type MatrixSliceMut3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U3, SliceStorageMut<'a, T, U3, U3, RStride, CStride>>;
Matrix<T, U3, U3, ViewStorageMut<'a, T, U3, U3, RStride, CStride>>;
/// A column-major 4x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4)]
pub type MatrixSliceMut4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U4, SliceStorageMut<'a, T, U4, U4, RStride, CStride>>;
Matrix<T, U4, U4, ViewStorageMut<'a, T, U4, U4, RStride, CStride>>;
/// A column-major 5x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5)]
pub type MatrixSliceMut5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U5, SliceStorageMut<'a, T, U5, U5, RStride, CStride>>;
Matrix<T, U5, U5, ViewStorageMut<'a, T, U5, U5, RStride, CStride>>;
/// A column-major 6x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6)]
pub type MatrixSliceMut6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U6, SliceStorageMut<'a, T, U6, U6, RStride, CStride>>;
Matrix<T, U6, U6, ViewStorageMut<'a, T, U6, U6, RStride, CStride>>;
/// A column-major 1x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1x2)]
pub type MatrixSliceMut1x2<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U2, SliceStorageMut<'a, T, U1, U2, RStride, CStride>>;
Matrix<T, U1, U2, ViewStorageMut<'a, T, U1, U2, RStride, CStride>>;
/// A column-major 1x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1x3)]
pub type MatrixSliceMut1x3<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U3, SliceStorageMut<'a, T, U1, U3, RStride, CStride>>;
Matrix<T, U1, U3, ViewStorageMut<'a, T, U1, U3, RStride, CStride>>;
/// A column-major 1x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1x4)]
pub type MatrixSliceMut1x4<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U4, SliceStorageMut<'a, T, U1, U4, RStride, CStride>>;
Matrix<T, U1, U4, ViewStorageMut<'a, T, U1, U4, RStride, CStride>>;
/// A column-major 1x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1x5)]
pub type MatrixSliceMut1x5<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U5, SliceStorageMut<'a, T, U1, U5, RStride, CStride>>;
Matrix<T, U1, U5, ViewStorageMut<'a, T, U1, U5, RStride, CStride>>;
/// A column-major 1x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut1x6)]
pub type MatrixSliceMut1x6<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U6, SliceStorageMut<'a, T, U1, U6, RStride, CStride>>;
Matrix<T, U1, U6, ViewStorageMut<'a, T, U1, U6, RStride, CStride>>;
/// A column-major 2x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2x1)]
pub type MatrixSliceMut2x1<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, SliceStorageMut<'a, T, U2, U1, RStride, CStride>>;
Matrix<T, U2, U1, ViewStorageMut<'a, T, U2, U1, RStride, CStride>>;
/// A column-major 2x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2x3)]
pub type MatrixSliceMut2x3<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U3, SliceStorageMut<'a, T, U2, U3, RStride, CStride>>;
Matrix<T, U2, U3, ViewStorageMut<'a, T, U2, U3, RStride, CStride>>;
/// A column-major 2x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2x4)]
pub type MatrixSliceMut2x4<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U4, SliceStorageMut<'a, T, U2, U4, RStride, CStride>>;
Matrix<T, U2, U4, ViewStorageMut<'a, T, U2, U4, RStride, CStride>>;
/// A column-major 2x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2x5)]
pub type MatrixSliceMut2x5<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U5, SliceStorageMut<'a, T, U2, U5, RStride, CStride>>;
Matrix<T, U2, U5, ViewStorageMut<'a, T, U2, U5, RStride, CStride>>;
/// A column-major 2x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut2x6)]
pub type MatrixSliceMut2x6<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U6, SliceStorageMut<'a, T, U2, U6, RStride, CStride>>;
Matrix<T, U2, U6, ViewStorageMut<'a, T, U2, U6, RStride, CStride>>;
/// A column-major 3x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3x1)]
pub type MatrixSliceMut3x1<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, SliceStorageMut<'a, T, U3, U1, RStride, CStride>>;
Matrix<T, U3, U1, ViewStorageMut<'a, T, U3, U1, RStride, CStride>>;
/// A column-major 3x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3x2)]
pub type MatrixSliceMut3x2<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U2, SliceStorageMut<'a, T, U3, U2, RStride, CStride>>;
Matrix<T, U3, U2, ViewStorageMut<'a, T, U3, U2, RStride, CStride>>;
/// A column-major 3x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3x4)]
pub type MatrixSliceMut3x4<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U4, SliceStorageMut<'a, T, U3, U4, RStride, CStride>>;
Matrix<T, U3, U4, ViewStorageMut<'a, T, U3, U4, RStride, CStride>>;
/// A column-major 3x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3x5)]
pub type MatrixSliceMut3x5<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U5, SliceStorageMut<'a, T, U3, U5, RStride, CStride>>;
Matrix<T, U3, U5, ViewStorageMut<'a, T, U3, U5, RStride, CStride>>;
/// A column-major 3x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut3x6)]
pub type MatrixSliceMut3x6<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U6, SliceStorageMut<'a, T, U3, U6, RStride, CStride>>;
Matrix<T, U3, U6, ViewStorageMut<'a, T, U3, U6, RStride, CStride>>;
/// A column-major 4x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4x1)]
pub type MatrixSliceMut4x1<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, SliceStorageMut<'a, T, U4, U1, RStride, CStride>>;
Matrix<T, U4, U1, ViewStorageMut<'a, T, U4, U1, RStride, CStride>>;
/// A column-major 4x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4x2)]
pub type MatrixSliceMut4x2<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U2, SliceStorageMut<'a, T, U4, U2, RStride, CStride>>;
Matrix<T, U4, U2, ViewStorageMut<'a, T, U4, U2, RStride, CStride>>;
/// A column-major 4x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4x3)]
pub type MatrixSliceMut4x3<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U3, SliceStorageMut<'a, T, U4, U3, RStride, CStride>>;
Matrix<T, U4, U3, ViewStorageMut<'a, T, U4, U3, RStride, CStride>>;
/// A column-major 4x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4x5)]
pub type MatrixSliceMut4x5<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U5, SliceStorageMut<'a, T, U4, U5, RStride, CStride>>;
Matrix<T, U4, U5, ViewStorageMut<'a, T, U4, U5, RStride, CStride>>;
/// A column-major 4x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut4x6)]
pub type MatrixSliceMut4x6<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U6, SliceStorageMut<'a, T, U4, U6, RStride, CStride>>;
Matrix<T, U4, U6, ViewStorageMut<'a, T, U4, U6, RStride, CStride>>;
/// A column-major 5x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5x1)]
pub type MatrixSliceMut5x1<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, SliceStorageMut<'a, T, U5, U1, RStride, CStride>>;
Matrix<T, U5, U1, ViewStorageMut<'a, T, U5, U1, RStride, CStride>>;
/// A column-major 5x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5x2)]
pub type MatrixSliceMut5x2<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U2, SliceStorageMut<'a, T, U5, U2, RStride, CStride>>;
Matrix<T, U5, U2, ViewStorageMut<'a, T, U5, U2, RStride, CStride>>;
/// A column-major 5x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5x3)]
pub type MatrixSliceMut5x3<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U3, SliceStorageMut<'a, T, U5, U3, RStride, CStride>>;
Matrix<T, U5, U3, ViewStorageMut<'a, T, U5, U3, RStride, CStride>>;
/// A column-major 5x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5x4)]
pub type MatrixSliceMut5x4<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U4, SliceStorageMut<'a, T, U5, U4, RStride, CStride>>;
Matrix<T, U5, U4, ViewStorageMut<'a, T, U5, U4, RStride, CStride>>;
/// A column-major 5x6 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut5x6)]
pub type MatrixSliceMut5x6<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U6, SliceStorageMut<'a, T, U5, U6, RStride, CStride>>;
Matrix<T, U5, U6, ViewStorageMut<'a, T, U5, U6, RStride, CStride>>;
/// A column-major 6x1 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6x1)]
pub type MatrixSliceMut6x1<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, SliceStorageMut<'a, T, U6, U1, RStride, CStride>>;
Matrix<T, U6, U1, ViewStorageMut<'a, T, U6, U1, RStride, CStride>>;
/// A column-major 6x2 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6x2)]
pub type MatrixSliceMut6x2<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U2, SliceStorageMut<'a, T, U6, U2, RStride, CStride>>;
Matrix<T, U6, U2, ViewStorageMut<'a, T, U6, U2, RStride, CStride>>;
/// A column-major 6x3 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6x3)]
pub type MatrixSliceMut6x3<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U3, SliceStorageMut<'a, T, U6, U3, RStride, CStride>>;
Matrix<T, U6, U3, ViewStorageMut<'a, T, U6, U3, RStride, CStride>>;
/// A column-major 6x4 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6x4)]
pub type MatrixSliceMut6x4<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U4, SliceStorageMut<'a, T, U6, U4, RStride, CStride>>;
Matrix<T, U6, U4, ViewStorageMut<'a, T, U6, U4, RStride, CStride>>;
/// A column-major 6x5 matrix slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(MatrixViewMut6x5)]
pub type MatrixSliceMut6x5<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U5, SliceStorageMut<'a, T, U6, U5, RStride, CStride>>;
Matrix<T, U6, U5, ViewStorageMut<'a, T, U6, U5, RStride, CStride>>;
/// A column-major matrix slice with 1 row and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut1xX)]
pub type MatrixSliceMut1xX<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, Dynamic, SliceStorageMut<'a, T, U1, Dynamic, RStride, CStride>>;
Matrix<T, U1, Dyn, ViewStorageMut<'a, T, U1, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 2 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut2xX)]
pub type MatrixSliceMut2xX<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, Dynamic, SliceStorageMut<'a, T, U2, Dynamic, RStride, CStride>>;
Matrix<T, U2, Dyn, ViewStorageMut<'a, T, U2, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 3 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut3xX)]
pub type MatrixSliceMut3xX<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, Dynamic, SliceStorageMut<'a, T, U3, Dynamic, RStride, CStride>>;
Matrix<T, U3, Dyn, ViewStorageMut<'a, T, U3, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 4 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut4xX)]
pub type MatrixSliceMut4xX<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, Dynamic, SliceStorageMut<'a, T, U4, Dynamic, RStride, CStride>>;
Matrix<T, U4, Dyn, ViewStorageMut<'a, T, U4, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 5 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut5xX)]
pub type MatrixSliceMut5xX<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, Dynamic, SliceStorageMut<'a, T, U5, Dynamic, RStride, CStride>>;
Matrix<T, U5, Dyn, ViewStorageMut<'a, T, U5, Dyn, RStride, CStride>>;
/// A column-major matrix slice with 6 rows and a number of columns chosen at runtime.
#[deprecated = slice_deprecation_note!(MatrixViewMut6xX)]
pub type MatrixSliceMut6xX<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, Dynamic, SliceStorageMut<'a, T, U6, Dynamic, RStride, CStride>>;
Matrix<T, U6, Dyn, ViewStorageMut<'a, T, U6, Dyn, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 1 column.
pub type MatrixSliceMutXx1<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U1, SliceStorageMut<'a, T, Dynamic, U1, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx1)]
pub type MatrixSliceMutXx1<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorageMut<'a, T, Dyn, U1, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 2 columns.
pub type MatrixSliceMutXx2<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U2, SliceStorageMut<'a, T, Dynamic, U2, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx2)]
pub type MatrixSliceMutXx2<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U2, ViewStorageMut<'a, T, Dyn, U2, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 3 columns.
pub type MatrixSliceMutXx3<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U3, SliceStorageMut<'a, T, Dynamic, U3, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx3)]
pub type MatrixSliceMutXx3<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U3, ViewStorageMut<'a, T, Dyn, U3, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 4 columns.
pub type MatrixSliceMutXx4<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U4, SliceStorageMut<'a, T, Dynamic, U4, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx4)]
pub type MatrixSliceMutXx4<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U4, ViewStorageMut<'a, T, Dyn, U4, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 5 columns.
pub type MatrixSliceMutXx5<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U5, SliceStorageMut<'a, T, Dynamic, U5, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx5)]
pub type MatrixSliceMutXx5<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U5, ViewStorageMut<'a, T, Dyn, U5, RStride, CStride>>;
/// A column-major matrix slice with a number of rows chosen at runtime and 6 columns.
pub type MatrixSliceMutXx6<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U6, SliceStorageMut<'a, T, Dynamic, U6, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(MatrixViewMutXx6)]
pub type MatrixSliceMutXx6<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U6, ViewStorageMut<'a, T, Dyn, U6, RStride, CStride>>;
/// A column vector slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut)]
pub type VectorSliceMut<'a, T, D, RStride = U1, CStride = D> =
Matrix<T, D, U1, SliceStorageMut<'a, T, D, U1, RStride, CStride>>;
Matrix<T, D, U1, ViewStorageMut<'a, T, D, U1, RStride, CStride>>;
/// A column vector slice with dimensions known at compile-time.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(SVectorViewMut)]
pub type SVectorSliceMut<'a, T, const D: usize> =
Matrix<T, Const<D>, Const<1>, SliceStorageMut<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
Matrix<T, Const<D>, Const<1>, ViewStorageMut<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
/// A column vector slice dynamic numbers of rows and columns.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DVectorSliceMut<'a, T, RStride = U1, CStride = Dynamic> =
Matrix<T, Dynamic, U1, SliceStorageMut<'a, T, Dynamic, U1, RStride, CStride>>;
#[deprecated = slice_deprecation_note!(DVectorViewMut)]
pub type DVectorSliceMut<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorageMut<'a, T, Dyn, U1, RStride, CStride>>;
/// A 1D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut1)]
pub type VectorSliceMut1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, SliceStorageMut<'a, T, U1, U1, RStride, CStride>>;
Matrix<T, U1, U1, ViewStorageMut<'a, T, U1, U1, RStride, CStride>>;
/// A 2D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut2)]
pub type VectorSliceMut2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, SliceStorageMut<'a, T, U2, U1, RStride, CStride>>;
Matrix<T, U2, U1, ViewStorageMut<'a, T, U2, U1, RStride, CStride>>;
/// A 3D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut3)]
pub type VectorSliceMut3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, SliceStorageMut<'a, T, U3, U1, RStride, CStride>>;
Matrix<T, U3, U1, ViewStorageMut<'a, T, U3, U1, RStride, CStride>>;
/// A 4D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut4)]
pub type VectorSliceMut4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, SliceStorageMut<'a, T, U4, U1, RStride, CStride>>;
Matrix<T, U4, U1, ViewStorageMut<'a, T, U4, U1, RStride, CStride>>;
/// A 5D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut5)]
pub type VectorSliceMut5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, SliceStorageMut<'a, T, U5, U1, RStride, CStride>>;
Matrix<T, U5, U1, ViewStorageMut<'a, T, U5, U1, RStride, CStride>>;
/// A 6D column vector slice.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
#[deprecated = slice_deprecation_note!(VectorViewMut6)]
pub type VectorSliceMut6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, SliceStorageMut<'a, T, U6, U1, RStride, CStride>>;
Matrix<T, U6, U1, ViewStorageMut<'a, T, U6, U1, RStride, CStride>>;

875
src/base/alias_view.rs Normal file
View File

@ -0,0 +1,875 @@
use crate::base::dimension::{Dyn, U1, U2, U3, U4, U5, U6};
use crate::base::matrix_view::{ViewStorage, ViewStorageMut};
use crate::base::{Const, Matrix};
/*
*
*
* Matrix view aliases.
*
*
*/
// NOTE: we can't provide defaults for the strides because it's not supported yet by min_const_generics.
/// An immutable column-major matrix view with dimensions known at compile-time.
///
/// See [`SMatrixViewMut`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type SMatrixView<'a, T, const R: usize, const C: usize> =
Matrix<T, Const<R>, Const<C>, ViewStorage<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
/// An immutable column-major matrix view dynamic numbers of rows and columns.
///
/// See [`DMatrixViewMut`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixView<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, Dyn, ViewStorage<'a, T, Dyn, Dyn, RStride, CStride>>;
/// An immutable column-major 1x1 matrix view.
///
/// See [`MatrixViewMut1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, ViewStorage<'a, T, U1, U1, RStride, CStride>>;
/// An immutable column-major 2x2 matrix view.
///
/// See [`MatrixViewMut2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U2, ViewStorage<'a, T, U2, U2, RStride, CStride>>;
/// An immutable column-major 3x3 matrix view.
///
/// See [`MatrixViewMut3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U3, ViewStorage<'a, T, U3, U3, RStride, CStride>>;
/// An immutable column-major 4x4 matrix view.
///
/// See [`MatrixViewMut4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U4, ViewStorage<'a, T, U4, U4, RStride, CStride>>;
/// An immutable column-major 5x5 matrix view.
///
/// See [`MatrixViewMut5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U5, ViewStorage<'a, T, U5, U5, RStride, CStride>>;
/// An immutable column-major 6x6 matrix view.
///
/// See [`MatrixViewMut6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U6, ViewStorage<'a, T, U6, U6, RStride, CStride>>;
/// An immutable column-major 1x2 matrix view.
///
/// See [`MatrixViewMut1x2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1x2<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U2, ViewStorage<'a, T, U1, U2, RStride, CStride>>;
/// An immutable column-major 1x3 matrix view.
///
/// See [`MatrixViewMut1x3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1x3<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U3, ViewStorage<'a, T, U1, U3, RStride, CStride>>;
/// An immutable column-major 1x4 matrix view.
///
/// See [`MatrixViewMut1x4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1x4<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U4, ViewStorage<'a, T, U1, U4, RStride, CStride>>;
/// An immutable column-major 1x5 matrix view.
///
/// See [`MatrixViewMut1x5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1x5<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U5, ViewStorage<'a, T, U1, U5, RStride, CStride>>;
/// An immutable column-major 1x6 matrix view.
///
/// See [`MatrixViewMut1x6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1x6<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U6, ViewStorage<'a, T, U1, U6, RStride, CStride>>;
/// An immutable column-major 2x1 matrix view.
///
/// See [`MatrixViewMut2x1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2x1<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, ViewStorage<'a, T, U2, U1, RStride, CStride>>;
/// An immutable column-major 2x3 matrix view.
///
/// See [`MatrixViewMut2x3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2x3<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U3, ViewStorage<'a, T, U2, U3, RStride, CStride>>;
/// An immutable column-major 2x4 matrix view.
///
/// See [`MatrixViewMut2x4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2x4<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U4, ViewStorage<'a, T, U2, U4, RStride, CStride>>;
/// An immutable column-major 2x5 matrix view.
///
/// See [`MatrixViewMut2x5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2x5<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U5, ViewStorage<'a, T, U2, U5, RStride, CStride>>;
/// An immutable column-major 2x6 matrix view.
///
/// See [`MatrixViewMut2x6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2x6<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U6, ViewStorage<'a, T, U2, U6, RStride, CStride>>;
/// An immutable column-major 3x1 matrix view.
///
/// See [`MatrixViewMut3x1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3x1<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, ViewStorage<'a, T, U3, U1, RStride, CStride>>;
/// An immutable column-major 3x2 matrix view.
///
/// See [`MatrixViewMut3x2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3x2<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U2, ViewStorage<'a, T, U3, U2, RStride, CStride>>;
/// An immutable column-major 3x4 matrix view.
///
/// See [`MatrixViewMut3x4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3x4<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U4, ViewStorage<'a, T, U3, U4, RStride, CStride>>;
/// An immutable column-major 3x5 matrix view.
///
/// See [`MatrixViewMut3x5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3x5<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U5, ViewStorage<'a, T, U3, U5, RStride, CStride>>;
/// An immutable column-major 3x6 matrix view.
///
/// See [`MatrixViewMut3x6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3x6<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U6, ViewStorage<'a, T, U3, U6, RStride, CStride>>;
/// An immutable column-major 4x1 matrix view.
///
/// See [`MatrixViewMut4x1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4x1<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, ViewStorage<'a, T, U4, U1, RStride, CStride>>;
/// An immutable column-major 4x2 matrix view.
///
/// See [`MatrixViewMut4x2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4x2<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U2, ViewStorage<'a, T, U4, U2, RStride, CStride>>;
/// An immutable column-major 4x3 matrix view.
///
/// See [`MatrixViewMut4x3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4x3<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U3, ViewStorage<'a, T, U4, U3, RStride, CStride>>;
/// An immutable column-major 4x5 matrix view.
///
/// See [`MatrixViewMut4x5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4x5<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U5, ViewStorage<'a, T, U4, U5, RStride, CStride>>;
/// An immutable column-major 4x6 matrix view.
///
/// See [`MatrixViewMut4x6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4x6<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U6, ViewStorage<'a, T, U4, U6, RStride, CStride>>;
/// An immutable column-major 5x1 matrix view.
///
/// See [`MatrixViewMut5x1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5x1<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, ViewStorage<'a, T, U5, U1, RStride, CStride>>;
/// An immutable column-major 5x2 matrix view.
///
/// See [`MatrixViewMut5x2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5x2<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U2, ViewStorage<'a, T, U5, U2, RStride, CStride>>;
/// An immutable column-major 5x3 matrix view.
///
/// See [`MatrixViewMut5x3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5x3<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U3, ViewStorage<'a, T, U5, U3, RStride, CStride>>;
/// An immutable column-major 5x4 matrix view.
///
/// See [`MatrixViewMut5x4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5x4<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U4, ViewStorage<'a, T, U5, U4, RStride, CStride>>;
/// An immutable column-major 5x6 matrix view.
///
/// See [`MatrixViewMut5x6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5x6<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U6, ViewStorage<'a, T, U5, U6, RStride, CStride>>;
/// An immutable column-major 6x1 matrix view.
///
/// See [`MatrixViewMut6x1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6x1<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, ViewStorage<'a, T, U6, U1, RStride, CStride>>;
/// An immutable column-major 6x2 matrix view.
///
/// See [`MatrixViewMut6x2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6x2<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U2, ViewStorage<'a, T, U6, U2, RStride, CStride>>;
/// An immutable column-major 6x3 matrix view.
///
/// See [`MatrixViewMut6x3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6x3<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U3, ViewStorage<'a, T, U6, U3, RStride, CStride>>;
/// An immutable column-major 6x4 matrix view.
///
/// See [`MatrixViewMut6x4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6x4<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U4, ViewStorage<'a, T, U6, U4, RStride, CStride>>;
/// An immutable column-major 6x5 matrix view.
///
/// See [`MatrixViewMut6x5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6x5<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U5, ViewStorage<'a, T, U6, U5, RStride, CStride>>;
/// An immutable column-major matrix view with 1 row and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut1xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView1xX<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, Dyn, ViewStorage<'a, T, U1, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with 2 rows and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut2xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView2xX<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, Dyn, ViewStorage<'a, T, U2, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with 3 rows and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut3xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView3xX<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, Dyn, ViewStorage<'a, T, U3, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with 4 rows and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut4xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView4xX<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, Dyn, ViewStorage<'a, T, U4, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with 5 rows and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut5xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView5xX<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, Dyn, ViewStorage<'a, T, U5, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with 6 rows and a number of columns chosen at runtime.
///
/// See [`MatrixViewMut6xX`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixView6xX<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, Dyn, ViewStorage<'a, T, U6, Dyn, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 1 column.
///
/// See [`MatrixViewMutXx1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx1<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorage<'a, T, Dyn, U1, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 2 columns.
///
/// See [`MatrixViewMutXx2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx2<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U2, ViewStorage<'a, T, Dyn, U2, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 3 columns.
///
/// See [`MatrixViewMutXx3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx3<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U3, ViewStorage<'a, T, Dyn, U3, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 4 columns.
///
/// See [`MatrixViewMutXx4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx4<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U4, ViewStorage<'a, T, Dyn, U4, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 5 columns.
///
/// See [`MatrixViewMutXx5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx5<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U5, ViewStorage<'a, T, Dyn, U5, RStride, CStride>>;
/// An immutable column-major matrix view with a number of rows chosen at runtime and 6 columns.
///
/// See [`MatrixViewMutXx6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewXx6<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U6, ViewStorage<'a, T, Dyn, U6, RStride, CStride>>;
/// An immutable column vector view with dimensions known at compile-time.
///
/// See [`VectorViewMut`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView<'a, T, D, RStride = U1, CStride = D> =
Matrix<T, D, U1, ViewStorage<'a, T, D, U1, RStride, CStride>>;
/// An immutable column vector view with dimensions known at compile-time.
///
/// See [`SVectorViewMut`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type SVectorView<'a, T, const D: usize> =
Matrix<T, Const<D>, Const<1>, ViewStorage<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
/// An immutable column vector view dynamic numbers of rows and columns.
///
/// See [`DVectorViewMut`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DVectorView<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorage<'a, T, Dyn, U1, RStride, CStride>>;
/// An immutable 1D column vector view.
///
/// See [`VectorViewMut1`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, ViewStorage<'a, T, U1, U1, RStride, CStride>>;
/// An immutable 2D column vector view.
///
/// See [`VectorViewMut2`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, ViewStorage<'a, T, U2, U1, RStride, CStride>>;
/// An immutable 3D column vector view.
///
/// See [`VectorViewMut3`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, ViewStorage<'a, T, U3, U1, RStride, CStride>>;
/// An immutable 4D column vector view.
///
/// See [`VectorViewMut4`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, ViewStorage<'a, T, U4, U1, RStride, CStride>>;
/// An immutable 5D column vector view.
///
/// See [`VectorViewMut5`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, ViewStorage<'a, T, U5, U1, RStride, CStride>>;
/// An immutable 6D column vector view.
///
/// See [`VectorViewMut6`] for a mutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorView6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, ViewStorage<'a, T, U6, U1, RStride, CStride>>;
/*
*
*
* Same thing, but for mutable views.
*
*
*/
/// A mutable column-major matrix view with dimensions known at compile-time.
///
/// See [`SMatrixView`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type SMatrixViewMut<'a, T, const R: usize, const C: usize> =
Matrix<T, Const<R>, Const<C>, ViewStorageMut<'a, T, Const<R>, Const<C>, Const<1>, Const<R>>>;
/// A mutable column-major matrix view dynamic numbers of rows and columns.
///
/// See [`DMatrixView`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DMatrixViewMut<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, Dyn, ViewStorageMut<'a, T, Dyn, Dyn, RStride, CStride>>;
/// A mutable column-major 1x1 matrix view.
///
/// See [`MatrixView1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, ViewStorageMut<'a, T, U1, U1, RStride, CStride>>;
/// A mutable column-major 2x2 matrix view.
///
/// See [`MatrixView2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U2, ViewStorageMut<'a, T, U2, U2, RStride, CStride>>;
/// A mutable column-major 3x3 matrix view.
///
/// See [`MatrixView3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U3, ViewStorageMut<'a, T, U3, U3, RStride, CStride>>;
/// A mutable column-major 4x4 matrix view.
///
/// See [`MatrixView4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U4, ViewStorageMut<'a, T, U4, U4, RStride, CStride>>;
/// A mutable column-major 5x5 matrix view.
///
/// See [`MatrixView5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U5, ViewStorageMut<'a, T, U5, U5, RStride, CStride>>;
/// A mutable column-major 6x6 matrix view.
///
/// See [`MatrixView6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U6, ViewStorageMut<'a, T, U6, U6, RStride, CStride>>;
/// A mutable column-major 1x2 matrix view.
///
/// See [`MatrixView1x2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1x2<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U2, ViewStorageMut<'a, T, U1, U2, RStride, CStride>>;
/// A mutable column-major 1x3 matrix view.
///
/// See [`MatrixView1x3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1x3<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U3, ViewStorageMut<'a, T, U1, U3, RStride, CStride>>;
/// A mutable column-major 1x4 matrix view.
///
/// See [`MatrixView1x4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1x4<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U4, ViewStorageMut<'a, T, U1, U4, RStride, CStride>>;
/// A mutable column-major 1x5 matrix view.
///
/// See [`MatrixView1x5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1x5<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U5, ViewStorageMut<'a, T, U1, U5, RStride, CStride>>;
/// A mutable column-major 1x6 matrix view.
///
/// See [`MatrixView1x6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1x6<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U6, ViewStorageMut<'a, T, U1, U6, RStride, CStride>>;
/// A mutable column-major 2x1 matrix view.
///
/// See [`MatrixView2x1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2x1<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, ViewStorageMut<'a, T, U2, U1, RStride, CStride>>;
/// A mutable column-major 2x3 matrix view.
///
/// See [`MatrixView2x3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2x3<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U3, ViewStorageMut<'a, T, U2, U3, RStride, CStride>>;
/// A mutable column-major 2x4 matrix view.
///
/// See [`MatrixView2x4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2x4<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U4, ViewStorageMut<'a, T, U2, U4, RStride, CStride>>;
/// A mutable column-major 2x5 matrix view.
///
/// See [`MatrixView2x5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2x5<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U5, ViewStorageMut<'a, T, U2, U5, RStride, CStride>>;
/// A mutable column-major 2x6 matrix view.
///
/// See [`MatrixView2x6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2x6<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U6, ViewStorageMut<'a, T, U2, U6, RStride, CStride>>;
/// A mutable column-major 3x1 matrix view.
///
/// See [`MatrixView3x1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3x1<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, ViewStorageMut<'a, T, U3, U1, RStride, CStride>>;
/// A mutable column-major 3x2 matrix view.
///
/// See [`MatrixView3x2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3x2<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U2, ViewStorageMut<'a, T, U3, U2, RStride, CStride>>;
/// A mutable column-major 3x4 matrix view.
///
/// See [`MatrixView3x4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3x4<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U4, ViewStorageMut<'a, T, U3, U4, RStride, CStride>>;
/// A mutable column-major 3x5 matrix view.
///
/// See [`MatrixView3x5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3x5<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U5, ViewStorageMut<'a, T, U3, U5, RStride, CStride>>;
/// A mutable column-major 3x6 matrix view.
///
/// See [`MatrixView3x6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3x6<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U6, ViewStorageMut<'a, T, U3, U6, RStride, CStride>>;
/// A mutable column-major 4x1 matrix view.
///
/// See [`MatrixView4x1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4x1<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, ViewStorageMut<'a, T, U4, U1, RStride, CStride>>;
/// A mutable column-major 4x2 matrix view.
///
/// See [`MatrixView4x2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4x2<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U2, ViewStorageMut<'a, T, U4, U2, RStride, CStride>>;
/// A mutable column-major 4x3 matrix view.
///
/// See [`MatrixView4x3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4x3<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U3, ViewStorageMut<'a, T, U4, U3, RStride, CStride>>;
/// A mutable column-major 4x5 matrix view.
///
/// See [`MatrixView4x5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4x5<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U5, ViewStorageMut<'a, T, U4, U5, RStride, CStride>>;
/// A mutable column-major 4x6 matrix view.
///
/// See [`MatrixView4x6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4x6<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U6, ViewStorageMut<'a, T, U4, U6, RStride, CStride>>;
/// A mutable column-major 5x1 matrix view.
///
/// See [`MatrixView5x1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5x1<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, ViewStorageMut<'a, T, U5, U1, RStride, CStride>>;
/// A mutable column-major 5x2 matrix view.
///
/// See [`MatrixView5x2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5x2<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U2, ViewStorageMut<'a, T, U5, U2, RStride, CStride>>;
/// A mutable column-major 5x3 matrix view.
///
/// See [`MatrixView5x3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5x3<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U3, ViewStorageMut<'a, T, U5, U3, RStride, CStride>>;
/// A mutable column-major 5x4 matrix view.
///
/// See [`MatrixView5x4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5x4<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U4, ViewStorageMut<'a, T, U5, U4, RStride, CStride>>;
/// A mutable column-major 5x6 matrix view.
///
/// See [`MatrixView5x6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5x6<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U6, ViewStorageMut<'a, T, U5, U6, RStride, CStride>>;
/// A mutable column-major 6x1 matrix view.
///
/// See [`MatrixView6x1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6x1<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, ViewStorageMut<'a, T, U6, U1, RStride, CStride>>;
/// A mutable column-major 6x2 matrix view.
///
/// See [`MatrixView6x2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6x2<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U2, ViewStorageMut<'a, T, U6, U2, RStride, CStride>>;
/// A mutable column-major 6x3 matrix view.
///
/// See [`MatrixView6x3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6x3<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U3, ViewStorageMut<'a, T, U6, U3, RStride, CStride>>;
/// A mutable column-major 6x4 matrix view.
///
/// See [`MatrixView6x4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6x4<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U4, ViewStorageMut<'a, T, U6, U4, RStride, CStride>>;
/// A mutable column-major 6x5 matrix view.
///
/// See [`MatrixView6x5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6x5<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U5, ViewStorageMut<'a, T, U6, U5, RStride, CStride>>;
/// A mutable column-major matrix view with 1 row and a number of columns chosen at runtime.
///
/// See [`MatrixView1xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut1xX<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, Dyn, ViewStorageMut<'a, T, U1, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with 2 rows and a number of columns chosen at runtime.
///
/// See [`MatrixView2xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut2xX<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, Dyn, ViewStorageMut<'a, T, U2, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with 3 rows and a number of columns chosen at runtime.
///
/// See [`MatrixView3xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut3xX<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, Dyn, ViewStorageMut<'a, T, U3, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with 4 rows and a number of columns chosen at runtime.
///
/// See [`MatrixView4xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut4xX<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, Dyn, ViewStorageMut<'a, T, U4, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with 5 rows and a number of columns chosen at runtime.
///
/// See [`MatrixView5xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut5xX<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, Dyn, ViewStorageMut<'a, T, U5, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with 6 rows and a number of columns chosen at runtime.
///
/// See [`MatrixView6xX`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMut6xX<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, Dyn, ViewStorageMut<'a, T, U6, Dyn, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 1 column.
///
/// See [`MatrixViewXx1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx1<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorageMut<'a, T, Dyn, U1, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 2 columns.
///
/// See [`MatrixViewXx2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx2<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U2, ViewStorageMut<'a, T, Dyn, U2, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 3 columns.
///
/// See [`MatrixViewXx3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx3<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U3, ViewStorageMut<'a, T, Dyn, U3, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 4 columns.
///
/// See [`MatrixViewXx4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx4<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U4, ViewStorageMut<'a, T, Dyn, U4, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 5 columns.
///
/// See [`MatrixViewXx5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx5<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U5, ViewStorageMut<'a, T, Dyn, U5, RStride, CStride>>;
/// A mutable column-major matrix view with a number of rows chosen at runtime and 6 columns.
///
/// See [`MatrixViewXx6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type MatrixViewMutXx6<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U6, ViewStorageMut<'a, T, Dyn, U6, RStride, CStride>>;
/// A mutable column vector view with dimensions known at compile-time.
///
/// See [`VectorView`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut<'a, T, D, RStride = U1, CStride = D> =
Matrix<T, D, U1, ViewStorageMut<'a, T, D, U1, RStride, CStride>>;
/// A mutable column vector view with dimensions known at compile-time.
///
/// See [`SVectorView`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type SVectorViewMut<'a, T, const D: usize> =
Matrix<T, Const<D>, Const<1>, ViewStorageMut<'a, T, Const<D>, Const<1>, Const<1>, Const<D>>>;
/// A mutable column vector view dynamic numbers of rows and columns.
///
/// See [`DVectorView`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type DVectorViewMut<'a, T, RStride = U1, CStride = Dyn> =
Matrix<T, Dyn, U1, ViewStorageMut<'a, T, Dyn, U1, RStride, CStride>>;
/// A mutable 1D column vector view.
///
/// See [`VectorView1`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut1<'a, T, RStride = U1, CStride = U1> =
Matrix<T, U1, U1, ViewStorageMut<'a, T, U1, U1, RStride, CStride>>;
/// A mutable 2D column vector view.
///
/// See [`VectorView2`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut2<'a, T, RStride = U1, CStride = U2> =
Matrix<T, U2, U1, ViewStorageMut<'a, T, U2, U1, RStride, CStride>>;
/// A mutable 3D column vector view.
///
/// See [`VectorView3`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut3<'a, T, RStride = U1, CStride = U3> =
Matrix<T, U3, U1, ViewStorageMut<'a, T, U3, U1, RStride, CStride>>;
/// A mutable 4D column vector view.
///
/// See [`VectorView4`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut4<'a, T, RStride = U1, CStride = U4> =
Matrix<T, U4, U1, ViewStorageMut<'a, T, U4, U1, RStride, CStride>>;
/// A mutable 5D column vector view.
///
/// See [`VectorView5`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut5<'a, T, RStride = U1, CStride = U5> =
Matrix<T, U5, U1, ViewStorageMut<'a, T, U5, U1, RStride, CStride>>;
/// A mutable 6D column vector view.
///
/// See [`VectorView6`] for an immutable version of this type.
///
/// **Because this is an alias, not all its methods are listed here. See the [`Matrix`](crate::base::Matrix) type too.**
pub type VectorViewMut6<'a, T, RStride = U1, CStride = U6> =
Matrix<T, U6, U1, ViewStorageMut<'a, T, U6, U1, RStride, CStride>>;

View File

@ -15,14 +15,14 @@ use std::mem::MaybeUninit;
///
/// An allocator is said to be:
/// static: if `R` and `C` both implement `DimName`.
/// dynamic: if either one (or both) of `R` or `C` is equal to `Dynamic`.
/// dynamic: if either one (or both) of `R` or `C` is equal to `Dyn`.
///
/// Every allocator must be both static and dynamic. Though not all implementations may share the
/// same `Buffer` type.
pub trait Allocator<T, R: Dim, C: Dim = U1>: Any + Sized {
/// The type of buffer this allocator can instanciate.
/// The type of buffer this allocator can instantiate.
type Buffer: StorageMut<T, R, C> + IsContiguous + Clone + Debug;
/// The type of buffer with uninitialized components this allocator can instanciate.
/// The type of buffer with uninitialized components this allocator can instantiate.
type BufferUninit: RawStorageMut<MaybeUninit<T>, R, C> + IsContiguous;
/// Allocates a buffer with the given number of rows and columns without initializing its content.
@ -41,6 +41,41 @@ pub trait Allocator<T, R: Dim, C: Dim = U1>: Any + Sized {
ncols: C,
iter: I,
) -> Self::Buffer;
#[inline]
/// Allocates a buffer initialized with the content of the given row-major order iterator.
fn allocate_from_row_iterator<I: IntoIterator<Item = T>>(
nrows: R,
ncols: C,
iter: I,
) -> Self::Buffer {
let mut res = Self::allocate_uninit(nrows, ncols);
let mut count = 0;
unsafe {
// OK because the allocated buffer is guaranteed to be contiguous.
let res_ptr = res.as_mut_slice_unchecked();
for (k, e) in iter
.into_iter()
.take(ncols.value() * nrows.value())
.enumerate()
{
let i = k / ncols.value();
let j = k % ncols.value();
// result[(i, j)] = e;
*res_ptr.get_unchecked_mut(i + j * nrows.value()) = MaybeUninit::new(e);
count += 1;
}
assert!(
count == nrows.value() * ncols.value(),
"Matrix init. from row iterator: iterator not long enough."
);
<Self as Allocator<T, R, C>>::assume_init(res)
}
}
}
/// A matrix reallocator. Changes the size of the memory buffer that initially contains (`RFrom` ×

View File

@ -5,12 +5,15 @@ use std::ops::Mul;
#[cfg(feature = "serde-serialize-no-std")]
use serde::de::{Error, SeqAccess, Visitor};
#[cfg(feature = "serde-serialize-no-std")]
use serde::ser::SerializeSeq;
use serde::ser::SerializeTuple;
#[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[cfg(feature = "serde-serialize-no-std")]
use std::marker::PhantomData;
#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;
use crate::base::allocator::Allocator;
use crate::base::default_allocator::DefaultAllocator;
use crate::base::dimension::{Const, ToTypenum};
@ -27,7 +30,18 @@ use std::mem;
/// A array-based statically sized matrix data storage.
#[repr(transparent)]
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(
as = "ArrayStorage<T::Archived, R, C>",
bound(archive = "
T: rkyv::Archive,
[[T; R]; C]: rkyv::Archive<Archived = [[T::Archived; R]; C]>
")
)
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct ArrayStorage<T, const R: usize, const C: usize>(pub [[T; R]; C]);
impl<T, const R: usize, const C: usize> ArrayStorage<T, R, C> {
@ -177,7 +191,7 @@ where
where
S: Serializer,
{
let mut serializer = serializer.serialize_seq(Some(R * C))?;
let mut serializer = serializer.serialize_tuple(R * C)?;
for e in self.as_slice().iter() {
serializer.serialize_element(e)?;
@ -196,7 +210,7 @@ where
where
D: Deserializer<'a>,
{
deserializer.deserialize_seq(ArrayStorageVisitor::new())
deserializer.deserialize_tuple(R * C, ArrayStorageVisitor::new())
}
}
@ -273,45 +287,3 @@ unsafe impl<T: Scalar + Copy + bytemuck::Pod, const R: usize, const C: usize> by
for ArrayStorage<T, R, C>
{
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::ArrayStorage;
use rkyv::{offset_of, project_struct, Archive, Deserialize, Fallible, Serialize};
impl<T: Archive, const R: usize, const C: usize> Archive for ArrayStorage<T, R, C> {
type Archived = ArrayStorage<T::Archived, R, C>;
type Resolver = <[[T; R]; C] as Archive>::Resolver;
fn resolve(
&self,
pos: usize,
resolver: Self::Resolver,
out: &mut core::mem::MaybeUninit<Self::Archived>,
) {
self.0.resolve(
pos + offset_of!(Self::Archived, 0),
resolver,
project_struct!(out: Self::Archived => 0),
);
}
}
impl<T: Serialize<S>, S: Fallible + ?Sized, const R: usize, const C: usize> Serialize<S>
for ArrayStorage<T, R, C>
{
fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
self.0.serialize(serializer)
}
}
impl<T: Archive, D: Fallible + ?Sized, const R: usize, const C: usize>
Deserialize<ArrayStorage<T, R, C>, D> for ArrayStorage<T::Archived, R, C>
where
T::Archived: Deserialize<T, D>,
{
fn deserialize(&self, deserializer: &mut D) -> Result<ArrayStorage<T, R, C>, D::Error> {
Ok(ArrayStorage(self.0.deserialize(deserializer)?))
}
}
}

View File

@ -7,11 +7,11 @@ use crate::base::blas_uninit::{axcpy_uninit, gemm_uninit, gemv_uninit};
use crate::base::constraint::{
AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
};
use crate::base::dimension::{Const, Dim, Dynamic, U1, U2, U3, U4};
use crate::base::dimension::{Const, Dim, Dyn, U1, U2, U3, U4};
use crate::base::storage::{Storage, StorageMut};
use crate::base::uninit::Init;
use crate::base::{
DVectorSlice, DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, VectorSlice,
DVectorView, DefaultAllocator, Matrix, Scalar, SquareMatrix, Vector, VectorView,
};
/// # Dot/scalar product
@ -363,8 +363,8 @@ where
x: &Vector<T, D3, SC>,
beta: T,
dot: impl Fn(
&DVectorSlice<'_, T, SB::RStride, SB::CStride>,
&DVectorSlice<'_, T, SC::RStride, SC::CStride>,
&DVectorView<'_, T, SB::RStride, SB::CStride>,
&DVectorView<'_, T, SC::RStride, SC::CStride>,
) -> T,
) where
T: One,
@ -393,7 +393,7 @@ where
let col2 = a.column(0);
let val = unsafe { x.vget_unchecked(0).clone() };
self.axpy(alpha.clone() * val, &col2, beta);
self[0] += alpha.clone() * dot(&a.slice_range(1.., 0), &x.rows_range(1..));
self[0] += alpha.clone() * dot(&a.view_range(1.., 0), &x.rows_range(1..));
for j in 1..dim2 {
let col2 = a.column(j);
@ -506,7 +506,7 @@ where
a: &Matrix<T, R2, C2, SB>,
x: &Vector<T, D3, SC>,
beta: T,
dot: impl Fn(&VectorSlice<'_, T, R2, SB::RStride, SB::CStride>, &Vector<T, D3, SC>) -> T,
dot: impl Fn(&VectorView<'_, T, R2, SB::RStride, SB::CStride>, &Vector<T, D3, SC>) -> T,
) where
T: One,
SB: Storage<T, R2, C2>,
@ -890,9 +890,9 @@ where
for j in 0..dim1 {
let val = unsafe { conjugate(y.vget_unchecked(j).clone()) };
let subdim = Dynamic::new(dim1 - j);
let subdim = Dyn(dim1 - j);
// TODO: avoid bound checks.
self.generic_slice_mut((j, j), (subdim, Const::<1>)).axpy(
self.generic_view_mut((j, j), (subdim, Const::<1>)).axpy(
alpha.clone() * val,
&x.rows_range(j..),
beta.clone(),

View File

@ -13,16 +13,17 @@ use matrixmultiply;
use num::{One, Zero};
use simba::scalar::{ClosedAdd, ClosedMul};
#[cfg(feature = "std")]
use std::mem;
use std::{any::TypeId, mem};
use crate::base::constraint::{
AreMultipliable, DimEq, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint,
};
use crate::base::dimension::{Dim, Dynamic, U1};
#[cfg(feature = "std")]
use crate::base::dimension::Dyn;
use crate::base::dimension::{Dim, U1};
use crate::base::storage::{RawStorage, RawStorageMut};
use crate::base::uninit::InitStatus;
use crate::base::{Matrix, Scalar, Vector};
use std::any::TypeId;
// # Safety
// The content of `y` must only contain values for which
@ -209,16 +210,16 @@ pub unsafe fn gemm_uninit<
#[cfg(feature = "std")]
{
// We assume large matrices will be Dynamic but small matrices static.
// We assume large matrices will be Dyn but small matrices static.
// We could use matrixmultiply for large statically-sized matrices but the performance
// threshold to activate it would be different from SMALL_DIM because our code optimizes
// better for statically-sized matrices.
if R1::is::<Dynamic>()
|| C1::is::<Dynamic>()
|| R2::is::<Dynamic>()
|| C2::is::<Dynamic>()
|| R3::is::<Dynamic>()
|| C3::is::<Dynamic>()
if R1::is::<Dyn>()
|| C1::is::<Dyn>()
|| R2::is::<Dyn>()
|| C2::is::<Dyn>()
|| R3::is::<Dyn>()
|| C3::is::<Dyn>()
{
// matrixmultiply can be used only if the std feature is available.
let nrows1 = y.nrows();

View File

@ -59,7 +59,7 @@ where
SB: Storage<T, DimNameDiff<D, U1>>,
{
let mut res = Self::identity();
res.generic_slice_mut(
res.generic_view_mut(
(0, D::dim() - 1),
(DimNameDiff::<D, U1>::name(), Const::<1>),
)
@ -382,19 +382,19 @@ impl<T: Scalar + Zero + One + ClosedMul + ClosedAdd, D: DimName, S: Storage<T, D
DefaultAllocator: Allocator<T, DimNameDiff<D, U1>>,
{
let scale = self
.generic_slice(
.generic_view(
(D::dim() - 1, 0),
(Const::<1>, DimNameDiff::<D, U1>::name()),
)
.tr_dot(shift);
let post_translation = self.generic_slice(
let post_translation = self.generic_view(
(0, 0),
(DimNameDiff::<D, U1>::name(), DimNameDiff::<D, U1>::name()),
) * shift;
self[(D::dim() - 1, D::dim() - 1)] += scale;
let mut translation = self.generic_slice_mut(
let mut translation = self.generic_view_mut(
(0, D::dim() - 1),
(DimNameDiff::<D, U1>::name(), Const::<1>),
);
@ -415,11 +415,11 @@ where
&self,
v: &OVector<T, DimNameDiff<D, U1>>,
) -> OVector<T, DimNameDiff<D, U1>> {
let transform = self.generic_slice(
let transform = self.generic_view(
(0, 0),
(DimNameDiff::<D, U1>::name(), DimNameDiff::<D, U1>::name()),
);
let normalizer = self.generic_slice(
let normalizer = self.generic_view(
(D::dim() - 1, 0),
(Const::<1>, DimNameDiff::<D, U1>::name()),
);
@ -437,9 +437,9 @@ impl<T: RealField, S: Storage<T, Const<3>, Const<3>>> SquareMatrix<T, Const<3>,
/// Transforms the given point, assuming the matrix `self` uses homogeneous coordinates.
#[inline]
pub fn transform_point(&self, pt: &Point<T, 2>) -> Point<T, 2> {
let transform = self.fixed_slice::<2, 2>(0, 0);
let translation = self.fixed_slice::<2, 1>(0, 2);
let normalizer = self.fixed_slice::<1, 2>(2, 0);
let transform = self.fixed_view::<2, 2>(0, 0);
let translation = self.fixed_view::<2, 1>(0, 2);
let normalizer = self.fixed_view::<1, 2>(2, 0);
let n = normalizer.tr_dot(&pt.coords) + unsafe { self.get_unchecked((2, 2)).clone() };
if !n.is_zero() {
@ -454,9 +454,9 @@ impl<T: RealField, S: Storage<T, Const<4>, Const<4>>> SquareMatrix<T, Const<4>,
/// Transforms the given point, assuming the matrix `self` uses homogeneous coordinates.
#[inline]
pub fn transform_point(&self, pt: &Point<T, 3>) -> Point<T, 3> {
let transform = self.fixed_slice::<3, 3>(0, 0);
let translation = self.fixed_slice::<3, 1>(0, 3);
let normalizer = self.fixed_slice::<1, 3>(3, 0);
let transform = self.fixed_view::<3, 3>(0, 0);
let translation = self.fixed_view::<3, 1>(0, 3);
let normalizer = self.fixed_view::<1, 3>(3, 0);
let n = normalizer.tr_dot(&pt.coords) + unsafe { self.get_unchecked((3, 3)).clone() };
if !n.is_zero() {

View File

@ -1,12 +1,12 @@
//! Compatibility constraints between matrix shapes, e.g., for addition or multiplication.
use crate::base::dimension::{Dim, DimName, Dynamic};
use crate::base::dimension::{Dim, DimName, Dyn};
/// A type used in `where` clauses for enforcing constraints.
#[derive(Copy, Clone, Debug)]
pub struct ShapeConstraint;
/// Constraints `C1` and `R2` to be equivalent.
/// Constrains `C1` and `R2` to be equivalent.
pub trait AreMultipliable<R1: Dim, C1: Dim, R2: Dim, C2: Dim>: DimEq<C1, R2> {}
impl<R1: Dim, C1: Dim, R2: Dim, C2: Dim> AreMultipliable<R1, C1, R2, C2> for ShapeConstraint where
@ -14,7 +14,7 @@ impl<R1: Dim, C1: Dim, R2: Dim, C2: Dim> AreMultipliable<R1, C1, R2, C2> for Sha
{
}
/// Constraints `D1` and `D2` to be equivalent.
/// Constrains `D1` and `D2` to be equivalent.
pub trait DimEq<D1: Dim, D2: Dim> {
/// This is either equal to `D1` or `D2`, always choosing the one (if any) which is a type-level
/// constant.
@ -25,17 +25,17 @@ impl<D: Dim> DimEq<D, D> for ShapeConstraint {
type Representative = D;
}
impl<D: DimName> DimEq<D, Dynamic> for ShapeConstraint {
impl<D: DimName> DimEq<D, Dyn> for ShapeConstraint {
type Representative = D;
}
impl<D: DimName> DimEq<Dynamic, D> for ShapeConstraint {
impl<D: DimName> DimEq<Dyn, D> for ShapeConstraint {
type Representative = D;
}
macro_rules! equality_trait_decl(
($($doc: expr, $Trait: ident),* $(,)*) => {$(
// XXX: we can't do something like `DimEq<D1> for D2` because we would require a blancket impl…
// XXX: we can't do something like `DimEq<D1> for D2` because we would require a blanket impl…
#[doc = $doc]
pub trait $Trait<D1: Dim, D2: Dim>: DimEq<D1, D2> + DimEq<D2, D1> {
/// This is either equal to `D1` or `D2`, always choosing the one (if any) which is a type-level
@ -47,28 +47,28 @@ macro_rules! equality_trait_decl(
type Representative = D;
}
impl<D: DimName> $Trait<D, Dynamic> for ShapeConstraint {
impl<D: DimName> $Trait<D, Dyn> for ShapeConstraint {
type Representative = D;
}
impl<D: DimName> $Trait<Dynamic, D> for ShapeConstraint {
impl<D: DimName> $Trait<Dyn, D> for ShapeConstraint {
type Representative = D;
}
)*}
);
equality_trait_decl!(
"Constraints `D1` and `D2` to be equivalent. \
"Constrains `D1` and `D2` to be equivalent. \
They are both assumed to be the number of \
rows of a matrix.",
SameNumberOfRows,
"Constraints `D1` and `D2` to be equivalent. \
"Constrains `D1` and `D2` to be equivalent. \
They are both assumed to be the number of \
columns of a matrix.",
SameNumberOfColumns
);
/// Constraints D1 and D2 to be equivalent, where they both designate dimensions of algebraic
/// Constrains D1 and D2 to be equivalent, where they both designate dimensions of algebraic
/// entities (e.g. square matrices).
pub trait SameDimension<D1: Dim, D2: Dim>:
SameNumberOfRows<D1, D2> + SameNumberOfColumns<D1, D2>
@ -82,10 +82,10 @@ impl<D: Dim> SameDimension<D, D> for ShapeConstraint {
type Representative = D;
}
impl<D: DimName> SameDimension<D, Dynamic> for ShapeConstraint {
impl<D: DimName> SameDimension<D, Dyn> for ShapeConstraint {
type Representative = D;
}
impl<D: DimName> SameDimension<Dynamic, D> for ShapeConstraint {
impl<D: DimName> SameDimension<Dyn, D> for ShapeConstraint {
type Representative = D;
}

View File

@ -19,7 +19,7 @@ use typenum::{self, Cmp, Greater};
use simba::scalar::{ClosedAdd, ClosedMul};
use crate::base::allocator::Allocator;
use crate::base::dimension::{Dim, DimName, Dynamic, ToTypenum};
use crate::base::dimension::{Dim, DimName, Dyn, ToTypenum};
use crate::base::storage::RawStorage;
use crate::base::{
ArrayStorage, Const, DefaultAllocator, Matrix, OMatrix, OVector, Scalar, Unit, Vector,
@ -86,6 +86,17 @@ where
Self::from_data(DefaultAllocator::allocate_from_iterator(nrows, ncols, iter))
}
/// Creates a matrix with all its elements filled by an row-major order iterator.
#[inline]
pub fn from_row_iterator_generic<I>(nrows: R, ncols: C, iter: I) -> Self
where
I: IntoIterator<Item = T>,
{
Self::from_data(DefaultAllocator::allocate_from_row_iterator(
nrows, ncols, iter,
))
}
/// Creates a matrix with its elements filled with the components provided by a slice in
/// row-major order.
///
@ -215,7 +226,7 @@ where
SB: RawStorage<T, Const<1>, C>,
{
assert!(!rows.is_empty(), "At least one row must be given.");
let nrows = R::try_to_usize().unwrap_or_else(|| rows.len());
let nrows = R::try_to_usize().unwrap_or(rows.len());
let ncols = rows[0].len();
assert!(
rows.len() == nrows,
@ -257,7 +268,7 @@ where
SB: RawStorage<T, R>,
{
assert!(!columns.is_empty(), "At least one column must be given.");
let ncols = C::try_to_usize().unwrap_or_else(|| columns.len());
let ncols = C::try_to_usize().unwrap_or(columns.len());
let nrows = columns[0].len();
assert!(
columns.len() == ncols,
@ -306,12 +317,12 @@ where
///
/// # Example
/// ```
/// # use nalgebra::{Dynamic, DMatrix, Matrix, Const};
/// # use nalgebra::{Dyn, DMatrix, Matrix, Const};
///
/// let vec = vec![0, 1, 2, 3, 4, 5];
/// let vec_ptr = vec.as_ptr();
///
/// let matrix = Matrix::from_vec_generic(Dynamic::new(vec.len()), Const::<1>, vec);
/// let matrix = Matrix::from_vec_generic(Dyn(vec.len()), Const::<1>, vec);
/// let matrix_storage_ptr = matrix.data.as_vec().as_ptr();
///
/// // `matrix` is backed by exactly the same `Vec` as it was constructed from.
@ -479,6 +490,36 @@ macro_rules! impl_constructors(
Self::from_iterator_generic($($gargs, )* iter)
}
/// Creates a matrix or vector with all its elements filled by a row-major iterator.
///
/// The output matrix is filled row-by-row.
///
/// ## Example
/// ```
/// # use nalgebra::{Matrix2x3, Vector3, DVector, DMatrix};
/// # use std::iter;
///
/// let v = Vector3::from_row_iterator((0..3).into_iter());
/// // The additional argument represents the vector dimension.
/// let dv = DVector::from_row_iterator(3, (0..3).into_iter());
/// let m = Matrix2x3::from_row_iterator((0..6).into_iter());
/// // The two additional arguments represent the matrix dimensions.
/// let dm = DMatrix::from_row_iterator(2, 3, (0..6).into_iter());
///
/// // For Vectors from_row_iterator is identical to from_iterator
/// assert!(v.x == 0 && v.y == 1 && v.z == 2);
/// assert!(dv[0] == 0 && dv[1] == 1 && dv[2] == 2);
/// assert!(m.m11 == 0 && m.m12 == 1 && m.m13 == 2 &&
/// m.m21 == 3 && m.m22 == 4 && m.m23 == 5);
/// assert!(dm[(0, 0)] == 0 && dm[(0, 1)] == 1 && dm[(0, 2)] == 2 &&
/// dm[(1, 0)] == 3 && dm[(1, 1)] == 4 && dm[(1, 2)] == 5);
/// ```
#[inline]
pub fn from_row_iterator<I>($($args: usize,)* iter: I) -> Self
where I: IntoIterator<Item = T> {
Self::from_row_iterator_generic($($gargs, )* iter)
}
/// Creates a matrix or vector filled with the results of a function applied to each of its
/// component coordinates.
///
@ -615,35 +656,35 @@ where
}
/// # Constructors of matrices with a dynamic number of columns
impl<T: Scalar, R: DimName> OMatrix<T, R, Dynamic>
impl<T: Scalar, R: DimName> OMatrix<T, R, Dyn>
where
DefaultAllocator: Allocator<T, R, Dynamic>,
DefaultAllocator: Allocator<T, R, Dyn>,
{
impl_constructors!(R, Dynamic;
impl_constructors!(R, Dyn;
=> R: DimName;
R::name(), Dynamic::new(ncols);
R::name(), Dyn(ncols);
ncols);
}
/// # Constructors of dynamic vectors and matrices with a dynamic number of rows
impl<T: Scalar, C: DimName> OMatrix<T, Dynamic, C>
impl<T: Scalar, C: DimName> OMatrix<T, Dyn, C>
where
DefaultAllocator: Allocator<T, Dynamic, C>,
DefaultAllocator: Allocator<T, Dyn, C>,
{
impl_constructors!(Dynamic, C;
impl_constructors!(Dyn, C;
=> C: DimName;
Dynamic::new(nrows), C::name();
Dyn(nrows), C::name();
nrows);
}
/// # Constructors of fully dynamic matrices
impl<T: Scalar> OMatrix<T, Dynamic, Dynamic>
impl<T: Scalar> OMatrix<T, Dyn, Dyn>
where
DefaultAllocator: Allocator<T, Dynamic, Dynamic>,
DefaultAllocator: Allocator<T, Dyn, Dyn>,
{
impl_constructors!(Dynamic, Dynamic;
impl_constructors!(Dyn, Dyn;
;
Dynamic::new(nrows), Dynamic::new(ncols);
Dyn(nrows), Dyn(ncols);
nrows, ncols);
}
@ -749,19 +790,19 @@ impl_constructors_from_data!(data; R, C; // Arguments for Matri
R::name(), C::name(); // Arguments for `_generic` constructors.
); // Arguments for non-generic constructors.
impl_constructors_from_data!(data; R, Dynamic;
impl_constructors_from_data!(data; R, Dyn;
=> R: DimName;
R::name(), Dynamic::new(data.len() / R::dim());
R::name(), Dyn(data.len() / R::dim());
);
impl_constructors_from_data!(data; Dynamic, C;
impl_constructors_from_data!(data; Dyn, C;
=> C: DimName;
Dynamic::new(data.len() / C::dim()), C::name();
Dyn(data.len() / C::dim()), C::name();
);
impl_constructors_from_data!(data; Dynamic, Dynamic;
impl_constructors_from_data!(data; Dyn, Dyn;
;
Dynamic::new(nrows), Dynamic::new(ncols);
Dyn(nrows), Dyn(ncols);
nrows, ncols);
/*

View File

@ -1,18 +1,18 @@
use crate::base::dimension::{Const, Dim, DimName, Dynamic};
use crate::base::matrix_slice::{SliceStorage, SliceStorageMut};
use crate::base::{MatrixSlice, MatrixSliceMutMN, Scalar};
use crate::base::dimension::{Const, Dim, DimName, Dyn};
use crate::base::matrix_view::{ViewStorage, ViewStorageMut};
use crate::base::{MatrixView, MatrixViewMut, Scalar};
use num_rational::Ratio;
/// # Creating matrix slices from `&[T]`
/// # Creating matrix views from `&[T]`
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
MatrixSlice<'a, T, R, C, RStride, CStride>
MatrixView<'a, T, R, C, RStride, CStride>
{
/// Creates, without bound-checking, a matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates, without bounds checking, a matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// # Safety
/// This method is unsafe because the input data array is not checked to contain enough elements.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub unsafe fn from_slice_with_strides_generic_unchecked(
data: &'a [T],
@ -22,7 +22,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
rstride: RStride,
cstride: CStride,
) -> Self {
let data = SliceStorage::from_raw_parts(
let data = ViewStorage::from_raw_parts(
data.as_ptr().add(start),
(nrows, ncols),
(rstride, cstride),
@ -30,10 +30,10 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
Self::from_data(data)
}
/// Creates a matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates a matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// Panics if the input data array dose not contain enough elements.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub fn from_slice_with_strides_generic(
data: &'a [T],
@ -48,7 +48,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
assert!(
data.len() + cstride.value() + rstride.value()
>= ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
"Matrix slice: input data buffer to small."
"Matrix view: input data buffer too small."
);
unsafe {
@ -57,12 +57,12 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
}
}
impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSlice<'a, T, R, C> {
/// Creates, without bound-checking, a matrix slice from an array and with dimensions specified by generic types instances.
impl<'a, T: Scalar, R: Dim, C: Dim> MatrixView<'a, T, R, C> {
/// Creates, without bound-checking, a matrix view from an array and with dimensions specified by generic types instances.
///
/// # Safety
/// This method is unsafe because the input data array is not checked to contain enough elements.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub unsafe fn from_slice_generic_unchecked(
data: &'a [T],
@ -75,10 +75,10 @@ impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSlice<'a, T, R, C> {
)
}
/// Creates a matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates a matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// Panics if the input data array dose not contain enough elements.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub fn from_slice_generic(data: &'a [T], nrows: R, ncols: C) -> Self {
Self::from_slice_with_strides_generic(data, nrows, ncols, Const::<1>, nrows)
@ -87,8 +87,8 @@ impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSlice<'a, T, R, C> {
macro_rules! impl_constructors(
($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixSlice<'a, T, $($Dims),*> {
/// Creates a new matrix slice from the given data array.
impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixView<'a, T, $($Dims),*> {
/// Creates a new matrix view from the given data array.
///
/// Panics if `data` does not contain enough elements.
#[inline]
@ -96,26 +96,33 @@ macro_rules! impl_constructors(
Self::from_slice_generic(data, $($gargs),*)
}
/// Creates, without bound checking, a new matrix slice from the given data array.
/// Creates, without bound checking, a new matrix view from the given data array.
/// # Safety
/// `data[start..start+rstride * cstride]` must be within bounds.
#[inline]
pub unsafe fn from_slice_unchecked(data: &'a [T], start: usize, $($args: usize),*) -> Self {
Self::from_slice_generic_unchecked(data, start, $($gargs),*)
}
}
impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixSlice<'a, T, $($Dims,)* Dynamic, Dynamic> {
/// Creates a new matrix slice with the specified strides from the given data array.
impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixView<'a, T, $($Dims,)* Dyn, Dyn> {
/// Creates a new matrix view with the specified strides from the given data array.
///
/// Panics if `data` does not contain enough elements.
#[inline]
pub fn from_slice_with_strides(data: &'a [T], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
Self::from_slice_with_strides_generic(data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
Self::from_slice_with_strides_generic(data, $($gargs,)* Dyn(rstride), Dyn(cstride))
}
/// Creates, without bound checking, a new matrix slice with the specified strides from the given data array.
/// Creates, without bound checking, a new matrix view with the specified strides from the given data array.
///
/// # Safety
///
/// `start`, `rstride`, and `cstride`, with the given matrix size will not index
/// outside of `data`.
#[inline]
pub unsafe fn from_slice_with_strides_unchecked(data: &'a [T], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
Self::from_slice_with_strides_generic_unchecked(data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
Self::from_slice_with_strides_generic_unchecked(data, start, $($gargs,)* Dyn(rstride), Dyn(cstride))
}
}
}
@ -127,30 +134,30 @@ impl_constructors!(R, C; // Arguments for Matrix<T, ...,
R::name(), C::name(); // Arguments for `_generic` constructors.
); // Arguments for non-generic constructors.
impl_constructors!(R, Dynamic;
impl_constructors!(R, Dyn;
=> R: DimName;
R::name(), Dynamic::new(ncols);
R::name(), Dyn(ncols);
ncols);
impl_constructors!(Dynamic, C;
impl_constructors!(Dyn, C;
=> C: DimName;
Dynamic::new(nrows), C::name();
Dyn(nrows), C::name();
nrows);
impl_constructors!(Dynamic, Dynamic;
impl_constructors!(Dyn, Dyn;
;
Dynamic::new(nrows), Dynamic::new(ncols);
Dyn(nrows), Dyn(ncols);
nrows, ncols);
/// # Creating mutable matrix slices from `&mut [T]`
/// # Creating mutable matrix views from `&mut [T]`
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
MatrixSliceMutMN<'a, T, R, C, RStride, CStride>
MatrixViewMut<'a, T, R, C, RStride, CStride>
{
/// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates, without bound-checking, a mutable matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// # Safety
/// This method is unsafe because the input data array is not checked to contain enough elements.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub unsafe fn from_slice_with_strides_generic_unchecked(
data: &'a mut [T],
@ -160,7 +167,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
rstride: RStride,
cstride: CStride,
) -> Self {
let data = SliceStorageMut::from_raw_parts(
let data = ViewStorageMut::from_raw_parts(
data.as_mut_ptr().add(start),
(nrows, ncols),
(rstride, cstride),
@ -168,10 +175,10 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
Self::from_data(data)
}
/// Creates a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates a mutable matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// Panics if the input data array dose not contain enough elements.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R`, `C`, `RStride`, `CStride` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub fn from_slice_with_strides_generic(
data: &'a mut [T],
@ -186,7 +193,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
assert!(
data.len() + cstride.value() + rstride.value()
>= ncols.value() * cstride.value() + nrows.value() * rstride.value() + 1,
"Matrix slice: input data buffer to small."
"Matrix view: input data buffer too small."
);
assert!(
@ -208,7 +215,7 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
}
}
},
"Matrix slice: dimensions and strides result in aliased indices."
"Matrix view: dimensions and strides result in aliased indices."
);
unsafe {
@ -217,12 +224,12 @@ impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim>
}
}
impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, T, R, C> {
/// Creates, without bound-checking, a mutable matrix slice from an array and with dimensions specified by generic types instances.
impl<'a, T: Scalar, R: Dim, C: Dim> MatrixViewMut<'a, T, R, C> {
/// Creates, without bound-checking, a mutable matrix view from an array and with dimensions specified by generic types instances.
///
/// # Safety
/// This method is unsafe because the input data array is not checked to contain enough elements.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub unsafe fn from_slice_generic_unchecked(
data: &'a mut [T],
@ -235,10 +242,10 @@ impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, T, R, C> {
)
}
/// Creates a mutable matrix slice from an array and with dimensions and strides specified by generic types instances.
/// Creates a mutable matrix view from an array and with dimensions and strides specified by generic types instances.
///
/// Panics if the input data array dose not contain enough elements.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dynamic::new()`.
/// The generic types `R` and `C` can either be type-level integers or integers wrapped with `Dyn()`.
#[inline]
pub fn from_slice_generic(data: &'a mut [T], nrows: R, ncols: C) -> Self {
Self::from_slice_with_strides_generic(data, nrows, ncols, Const::<1>, nrows)
@ -247,8 +254,8 @@ impl<'a, T: Scalar, R: Dim, C: Dim> MatrixSliceMutMN<'a, T, R, C> {
macro_rules! impl_constructors_mut(
($($Dims: ty),*; $(=> $DimIdent: ident: $DimBound: ident),*; $($gargs: expr),*; $($args: ident),*) => {
impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixSliceMutMN<'a, T, $($Dims),*> {
/// Creates a new mutable matrix slice from the given data array.
impl<'a, T: Scalar, $($DimIdent: $DimBound),*> MatrixViewMut<'a, T, $($Dims),*> {
/// Creates a new mutable matrix view from the given data array.
///
/// Panics if `data` does not contain enough elements.
#[inline]
@ -256,28 +263,34 @@ macro_rules! impl_constructors_mut(
Self::from_slice_generic(data, $($gargs),*)
}
/// Creates, without bound checking, a new mutable matrix slice from the given data array.
/// Creates, without bound checking, a new mutable matrix view from the given data array.
///
/// # Safety
///
/// `data[start..start+(R * C)]` must be within bounds.
#[inline]
pub unsafe fn from_slice_unchecked(data: &'a mut [T], start: usize, $($args: usize),*) -> Self {
Self::from_slice_generic_unchecked(data, start, $($gargs),*)
}
}
impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixSliceMutMN<'a, T, $($Dims,)* Dynamic, Dynamic> {
/// Creates a new mutable matrix slice with the specified strides from the given data array.
impl<'a, T: Scalar, $($DimIdent: $DimBound, )*> MatrixViewMut<'a, T, $($Dims,)* Dyn, Dyn> {
/// Creates a new mutable matrix view with the specified strides from the given data array.
///
/// Panics if `data` does not contain enough elements.
#[inline]
pub fn from_slice_with_strides_mut(data: &'a mut [T], $($args: usize,)* rstride: usize, cstride: usize) -> Self {
Self::from_slice_with_strides_generic(
data, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
data, $($gargs,)* Dyn(rstride), Dyn(cstride))
}
/// Creates, without bound checking, a new mutable matrix slice with the specified strides from the given data array.
/// Creates, without bound checking, a new mutable matrix view with the specified strides from the given data array.
/// # Safety
/// `data[start..start+rstride * cstride]` must be within bounds.
#[inline]
pub unsafe fn from_slice_with_strides_unchecked(data: &'a mut [T], start: usize, $($args: usize,)* rstride: usize, cstride: usize) -> Self {
Self::from_slice_with_strides_generic_unchecked(
data, start, $($gargs,)* Dynamic::new(rstride), Dynamic::new(cstride))
data, start, $($gargs,)* Dyn(rstride), Dyn(cstride))
}
}
}
@ -289,17 +302,17 @@ impl_constructors_mut!(R, C; // Arguments for Matrix<T,
R::name(), C::name(); // Arguments for `_generic` constructors.
); // Arguments for non-generic constructors.
impl_constructors_mut!(R, Dynamic;
impl_constructors_mut!(R, Dyn;
=> R: DimName;
R::name(), Dynamic::new(ncols);
R::name(), Dyn(ncols);
ncols);
impl_constructors_mut!(Dynamic, C;
impl_constructors_mut!(Dyn, C;
=> C: DimName;
Dynamic::new(nrows), C::name();
Dyn(nrows), C::name();
nrows);
impl_constructors_mut!(Dynamic, Dynamic;
impl_constructors_mut!(Dyn, Dyn;
;
Dynamic::new(nrows), Dynamic::new(ncols);
Dyn(nrows), Dyn(ncols);
nrows, ncols);

View File

@ -8,22 +8,22 @@ use simba::simd::{PrimitiveSimdValue, SimdValue};
use crate::base::allocator::{Allocator, SameShapeAllocator};
use crate::base::constraint::{SameNumberOfColumns, SameNumberOfRows, ShapeConstraint};
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::dimension::Dynamic;
use crate::base::dimension::{
Const, Dim, DimName, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
Const, Dim, U1, U10, U11, U12, U13, U14, U15, U16, U2, U3, U4, U5, U6, U7, U8, U9,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::dimension::{DimName, Dyn};
use crate::base::iter::{MatrixIter, MatrixIterMut};
use crate::base::storage::{IsContiguous, RawStorage, RawStorageMut};
use crate::base::{
ArrayStorage, DVectorSlice, DVectorSliceMut, DefaultAllocator, Matrix, MatrixSlice,
MatrixSliceMut, OMatrix, Scalar,
ArrayStorage, DVectorView, DVectorViewMut, DefaultAllocator, Matrix, MatrixView, MatrixViewMut,
OMatrix, Scalar,
};
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::{DVector, RowDVector, VecStorage};
use crate::base::{SliceStorage, SliceStorageMut};
use crate::base::{ViewStorage, ViewStorageMut};
use crate::constraint::DimEq;
use crate::{IsNotStaticOne, RowSVector, SMatrix, SVector, VectorSlice, VectorSliceMut};
use crate::{IsNotStaticOne, RowSVector, SMatrix, SVector, VectorView, VectorViewMut};
use std::mem::MaybeUninit;
// TODO: too bad this won't work for slice conversions.
@ -98,6 +98,18 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorage<T, R, C>> IntoIterator
}
}
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
for Matrix<T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>
{
type Item = &'a T;
type IntoIter = MatrixIter<'a, T, R, C, ViewStorage<'a, T, R, C, RStride, CStride>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
MatrixIter::new_owned(self.data)
}
}
impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IntoIterator
for &'a mut Matrix<T, R, C, S>
{
@ -110,6 +122,18 @@ impl<'a, T: Scalar, R: Dim, C: Dim, S: RawStorageMut<T, R, C>> IntoIterator
}
}
impl<'a, T: Scalar, R: Dim, C: Dim, RStride: Dim, CStride: Dim> IntoIterator
for Matrix<T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>
{
type Item = &'a mut T;
type IntoIter = MatrixIterMut<'a, T, R, C, ViewStorageMut<'a, T, R, C, RStride, CStride>>;
#[inline]
fn into_iter(self) -> Self::IntoIter {
MatrixIterMut::new_owned_mut(self.data)
}
}
impl<T: Scalar, const D: usize> From<[T; D]> for SVector<T, D> {
#[inline]
fn from(arr: [T; D]) -> Self {
@ -126,19 +150,19 @@ impl<T: Scalar, const D: usize> From<SVector<T, D>> for [T; D] {
}
impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const D: usize>
From<VectorSlice<'a, T, Const<D>, RStride, CStride>> for [T; D]
From<VectorView<'a, T, Const<D>, RStride, CStride>> for [T; D]
{
#[inline]
fn from(vec: VectorSlice<'a, T, Const<D>, RStride, CStride>) -> Self {
fn from(vec: VectorView<'a, T, Const<D>, RStride, CStride>) -> Self {
vec.into_owned().into()
}
}
impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const D: usize>
From<VectorSliceMut<'a, T, Const<D>, RStride, CStride>> for [T; D]
From<VectorViewMut<'a, T, Const<D>, RStride, CStride>> for [T; D]
{
#[inline]
fn from(vec: VectorSliceMut<'a, T, Const<D>, RStride, CStride>) -> Self {
fn from(vec: VectorViewMut<'a, T, Const<D>, RStride, CStride>) -> Self {
vec.into_owned().into()
}
}
@ -221,19 +245,19 @@ impl<T: Scalar, const R: usize, const C: usize> From<SMatrix<T, R, C>> for [[T;
}
impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const R: usize, const C: usize>
From<MatrixSlice<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
From<MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
{
#[inline]
fn from(mat: MatrixSlice<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
fn from(mat: MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
mat.into_owned().into()
}
}
impl<'a, T: Scalar, RStride: Dim, CStride: Dim, const R: usize, const C: usize>
From<MatrixSliceMut<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
From<MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>> for [[T; R]; C]
{
#[inline]
fn from(mat: MatrixSliceMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
fn from(mat: MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
mat.into_owned().into()
}
}
@ -289,192 +313,183 @@ impl_from_into_asref_borrow_2D!(
);
impl<'a, T, RStride, CStride, const R: usize, const C: usize>
From<MatrixSlice<'a, T, Const<R>, Const<C>, RStride, CStride>>
From<MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>>
for Matrix<T, Const<R>, Const<C>, ArrayStorage<T, R, C>>
where
T: Scalar,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSlice<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixView<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T, C, RStride, CStride> From<MatrixSlice<'a, T, Dynamic, C, RStride, CStride>>
for Matrix<T, Dynamic, C, VecStorage<T, Dynamic, C>>
impl<'a, T, C, RStride, CStride> From<MatrixView<'a, T, Dyn, C, RStride, CStride>>
for Matrix<T, Dyn, C, VecStorage<T, Dyn, C>>
where
T: Scalar,
C: Dim,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSlice<'a, T, Dynamic, C, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixView<'a, T, Dyn, C, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T, R, RStride, CStride> From<MatrixSlice<'a, T, R, Dynamic, RStride, CStride>>
for Matrix<T, R, Dynamic, VecStorage<T, R, Dynamic>>
impl<'a, T, R, RStride, CStride> From<MatrixView<'a, T, R, Dyn, RStride, CStride>>
for Matrix<T, R, Dyn, VecStorage<T, R, Dyn>>
where
T: Scalar,
R: DimName,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSlice<'a, T, R, Dynamic, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixView<'a, T, R, Dyn, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
impl<'a, T, RStride, CStride, const R: usize, const C: usize>
From<MatrixSliceMut<'a, T, Const<R>, Const<C>, RStride, CStride>>
From<MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>>
for Matrix<T, Const<R>, Const<C>, ArrayStorage<T, R, C>>
where
T: Scalar,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSliceMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixViewMut<'a, T, Const<R>, Const<C>, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T, C, RStride, CStride> From<MatrixSliceMut<'a, T, Dynamic, C, RStride, CStride>>
for Matrix<T, Dynamic, C, VecStorage<T, Dynamic, C>>
impl<'a, T, C, RStride, CStride> From<MatrixViewMut<'a, T, Dyn, C, RStride, CStride>>
for Matrix<T, Dyn, C, VecStorage<T, Dyn, C>>
where
T: Scalar,
C: Dim,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSliceMut<'a, T, Dynamic, C, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixViewMut<'a, T, Dyn, C, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T, R, RStride, CStride> From<MatrixSliceMut<'a, T, R, Dynamic, RStride, CStride>>
for Matrix<T, R, Dynamic, VecStorage<T, R, Dynamic>>
impl<'a, T, R, RStride, CStride> From<MatrixViewMut<'a, T, R, Dyn, RStride, CStride>>
for Matrix<T, R, Dyn, VecStorage<T, R, Dyn>>
where
T: Scalar,
R: DimName,
RStride: Dim,
CStride: Dim,
{
fn from(matrix_slice: MatrixSliceMut<'a, T, R, Dynamic, RStride, CStride>) -> Self {
matrix_slice.into_owned()
fn from(matrix_view: MatrixViewMut<'a, T, R, Dyn, RStride, CStride>) -> Self {
matrix_view.into_owned()
}
}
impl<'a, T, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a Matrix<T, R, C, S>>
for MatrixSlice<'a, T, RSlice, CSlice, RStride, CStride>
impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a Matrix<T, R, C, S>>
for MatrixView<'a, T, RView, CView, RStride, CStride>
where
T: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
RView: Dim,
CView: Dim,
RStride: Dim,
CStride: Dim,
S: RawStorage<T, R, C>,
ShapeConstraint: DimEq<R, RSlice>
+ DimEq<C, CSlice>
+ DimEq<RStride, S::RStride>
+ DimEq<CStride, S::CStride>,
ShapeConstraint:
DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
{
fn from(m: &'a Matrix<T, R, C, S>) -> Self {
let (row, col) = m.shape_generic();
let row_slice = RSlice::from_usize(row.value());
let col_slice = CSlice::from_usize(col.value());
let rows_result = RView::from_usize(row.value());
let cols_result = CView::from_usize(col.value());
let (rstride, cstride) = m.strides();
let rstride_slice = RStride::from_usize(rstride);
let cstride_slice = CStride::from_usize(cstride);
let rstride_result = RStride::from_usize(rstride);
let cstride_result = CStride::from_usize(cstride);
unsafe {
let data = SliceStorage::from_raw_parts(
let data = ViewStorage::from_raw_parts(
m.data.ptr(),
(row_slice, col_slice),
(rstride_slice, cstride_slice),
(rows_result, cols_result),
(rstride_result, cstride_result),
);
Matrix::from_data_statically_unchecked(data)
}
}
}
impl<'a, T, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
for MatrixSlice<'a, T, RSlice, CSlice, RStride, CStride>
impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
for MatrixView<'a, T, RView, CView, RStride, CStride>
where
T: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
RView: Dim,
CView: Dim,
RStride: Dim,
CStride: Dim,
S: RawStorage<T, R, C>,
ShapeConstraint: DimEq<R, RSlice>
+ DimEq<C, CSlice>
+ DimEq<RStride, S::RStride>
+ DimEq<CStride, S::CStride>,
ShapeConstraint:
DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
{
fn from(m: &'a mut Matrix<T, R, C, S>) -> Self {
let (row, col) = m.shape_generic();
let row_slice = RSlice::from_usize(row.value());
let col_slice = CSlice::from_usize(col.value());
let rows_result = RView::from_usize(row.value());
let cols_result = CView::from_usize(col.value());
let (rstride, cstride) = m.strides();
let rstride_slice = RStride::from_usize(rstride);
let cstride_slice = CStride::from_usize(cstride);
let rstride_result = RStride::from_usize(rstride);
let cstride_result = CStride::from_usize(cstride);
unsafe {
let data = SliceStorage::from_raw_parts(
let data = ViewStorage::from_raw_parts(
m.data.ptr(),
(row_slice, col_slice),
(rstride_slice, cstride_slice),
(rows_result, cols_result),
(rstride_result, cstride_result),
);
Matrix::from_data_statically_unchecked(data)
}
}
}
impl<'a, T, R, C, RSlice, CSlice, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
for MatrixSliceMut<'a, T, RSlice, CSlice, RStride, CStride>
impl<'a, T, R, C, RView, CView, RStride, CStride, S> From<&'a mut Matrix<T, R, C, S>>
for MatrixViewMut<'a, T, RView, CView, RStride, CStride>
where
T: Scalar,
R: Dim,
C: Dim,
RSlice: Dim,
CSlice: Dim,
RView: Dim,
CView: Dim,
RStride: Dim,
CStride: Dim,
S: RawStorageMut<T, R, C>,
ShapeConstraint: DimEq<R, RSlice>
+ DimEq<C, CSlice>
+ DimEq<RStride, S::RStride>
+ DimEq<CStride, S::CStride>,
ShapeConstraint:
DimEq<R, RView> + DimEq<C, CView> + DimEq<RStride, S::RStride> + DimEq<CStride, S::CStride>,
{
fn from(m: &'a mut Matrix<T, R, C, S>) -> Self {
let (row, col) = m.shape_generic();
let row_slice = RSlice::from_usize(row.value());
let col_slice = CSlice::from_usize(col.value());
let rows_result = RView::from_usize(row.value());
let cols_result = CView::from_usize(col.value());
let (rstride, cstride) = m.strides();
let rstride_slice = RStride::from_usize(rstride);
let cstride_slice = CStride::from_usize(cstride);
let rstride_result = RStride::from_usize(rstride);
let cstride_result = CStride::from_usize(cstride);
unsafe {
let data = SliceStorageMut::from_raw_parts(
let data = ViewStorageMut::from_raw_parts(
m.data.ptr_mut(),
(row_slice, col_slice),
(rstride_slice, cstride_slice),
(rows_result, cols_result),
(rstride_result, cstride_result),
);
Matrix::from_data_statically_unchecked(data)
}
@ -482,7 +497,7 @@ where
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T: Scalar> From<Vec<T>> for DVector<T> {
impl<T: Scalar> From<Vec<T>> for DVector<T> {
#[inline]
fn from(vec: Vec<T>) -> Self {
Self::from_vec(vec)
@ -490,7 +505,7 @@ impl<'a, T: Scalar> From<Vec<T>> for DVector<T> {
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<'a, T: Scalar> From<Vec<T>> for RowDVector<T> {
impl<T: Scalar> From<Vec<T>> for RowDVector<T> {
#[inline]
fn from(vec: Vec<T>) -> Self {
Self::from_vec(vec)
@ -515,28 +530,28 @@ impl<'a, T: Scalar + Copy, R: Dim, C: Dim, S: RawStorageMut<T, R, C> + IsContigu
}
}
impl<'a, T: Scalar + Copy> From<&'a [T]> for DVectorSlice<'a, T> {
impl<'a, T: Scalar + Copy> From<&'a [T]> for DVectorView<'a, T> {
#[inline]
fn from(slice: &'a [T]) -> Self {
Self::from_slice(slice, slice.len())
}
}
impl<'a, T: Scalar> From<DVectorSlice<'a, T>> for &'a [T] {
fn from(vec: DVectorSlice<'a, T>) -> &'a [T] {
impl<'a, T: Scalar> From<DVectorView<'a, T>> for &'a [T] {
fn from(vec: DVectorView<'a, T>) -> &'a [T] {
vec.data.into_slice()
}
}
impl<'a, T: Scalar + Copy> From<&'a mut [T]> for DVectorSliceMut<'a, T> {
impl<'a, T: Scalar + Copy> From<&'a mut [T]> for DVectorViewMut<'a, T> {
#[inline]
fn from(slice: &'a mut [T]) -> Self {
Self::from_slice(slice, slice.len())
}
}
impl<'a, T: Scalar> From<DVectorSliceMut<'a, T>> for &'a mut [T] {
fn from(vec: DVectorSliceMut<'a, T>) -> &'a mut [T] {
impl<'a, T: Scalar> From<DVectorViewMut<'a, T>> for &'a mut [T] {
fn from(vec: DVectorViewMut<'a, T>) -> &'a mut [T] {
vec.data.into_slice_mut()
}
}

View File

@ -12,21 +12,23 @@ use alloc::vec::Vec;
use super::Const;
use crate::base::allocator::{Allocator, Reallocator};
use crate::base::array_storage::ArrayStorage;
use crate::base::dimension::Dim;
#[cfg(any(feature = "alloc", feature = "std"))]
use crate::base::dimension::Dynamic;
use crate::base::dimension::{Dim, DimName};
use crate::base::dimension::{DimName, Dyn};
use crate::base::storage::{RawStorage, RawStorageMut};
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::base::vec_storage::VecStorage;
use crate::base::Scalar;
use std::mem::{ManuallyDrop, MaybeUninit};
#[cfg(any(feature = "std", feature = "alloc"))]
use std::mem::ManuallyDrop;
use std::mem::MaybeUninit;
/*
*
* Allocator.
*
*/
/// An allocator based on `GenericArray` and `VecStorage` for statically-sized and dynamically-sized
/// An allocator based on [`ArrayStorage`] and [`VecStorage`] for statically-sized and dynamically-sized
/// matrices respectively.
#[derive(Copy, Clone, Debug)]
pub struct DefaultAllocator;
@ -82,15 +84,15 @@ impl<T: Scalar, const R: usize, const C: usize> Allocator<T, Const<R>, Const<C>>
}
}
// Dynamic - Static
// Dynamic - Dynamic
// Dyn - Static
// Dyn - Dyn
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, C: Dim> Allocator<T, Dynamic, C> for DefaultAllocator {
type Buffer = VecStorage<T, Dynamic, C>;
type BufferUninit = VecStorage<MaybeUninit<T>, Dynamic, C>;
impl<T: Scalar, C: Dim> Allocator<T, Dyn, C> for DefaultAllocator {
type Buffer = VecStorage<T, Dyn, C>;
type BufferUninit = VecStorage<MaybeUninit<T>, Dyn, C>;
#[inline]
fn allocate_uninit(nrows: Dynamic, ncols: C) -> VecStorage<MaybeUninit<T>, Dynamic, C> {
fn allocate_uninit(nrows: Dyn, ncols: C) -> VecStorage<MaybeUninit<T>, Dyn, C> {
let mut data = Vec::new();
let length = nrows.value() * ncols.value();
data.reserve_exact(length);
@ -99,9 +101,7 @@ impl<T: Scalar, C: Dim> Allocator<T, Dynamic, C> for DefaultAllocator {
}
#[inline]
unsafe fn assume_init(
uninit: VecStorage<MaybeUninit<T>, Dynamic, C>,
) -> VecStorage<T, Dynamic, C> {
unsafe fn assume_init(uninit: VecStorage<MaybeUninit<T>, Dyn, C>) -> VecStorage<T, Dyn, C> {
// Avoids a double-drop.
let (nrows, ncols) = uninit.shape();
let vec: Vec<_> = uninit.into();
@ -117,7 +117,7 @@ impl<T: Scalar, C: Dim> Allocator<T, Dynamic, C> for DefaultAllocator {
#[inline]
fn allocate_from_iterator<I: IntoIterator<Item = T>>(
nrows: Dynamic,
nrows: Dyn,
ncols: C,
iter: I,
) -> Self::Buffer {
@ -130,14 +130,14 @@ impl<T: Scalar, C: Dim> Allocator<T, Dynamic, C> for DefaultAllocator {
}
}
// Static - Dynamic
// Static - Dyn
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, R: DimName> Allocator<T, R, Dynamic> for DefaultAllocator {
type Buffer = VecStorage<T, R, Dynamic>;
type BufferUninit = VecStorage<MaybeUninit<T>, R, Dynamic>;
impl<T: Scalar, R: DimName> Allocator<T, R, Dyn> for DefaultAllocator {
type Buffer = VecStorage<T, R, Dyn>;
type BufferUninit = VecStorage<MaybeUninit<T>, R, Dyn>;
#[inline]
fn allocate_uninit(nrows: R, ncols: Dynamic) -> VecStorage<MaybeUninit<T>, R, Dynamic> {
fn allocate_uninit(nrows: R, ncols: Dyn) -> VecStorage<MaybeUninit<T>, R, Dyn> {
let mut data = Vec::new();
let length = nrows.value() * ncols.value();
data.reserve_exact(length);
@ -147,9 +147,7 @@ impl<T: Scalar, R: DimName> Allocator<T, R, Dynamic> for DefaultAllocator {
}
#[inline]
unsafe fn assume_init(
uninit: VecStorage<MaybeUninit<T>, R, Dynamic>,
) -> VecStorage<T, R, Dynamic> {
unsafe fn assume_init(uninit: VecStorage<MaybeUninit<T>, R, Dyn>) -> VecStorage<T, R, Dyn> {
// Avoids a double-drop.
let (nrows, ncols) = uninit.shape();
let vec: Vec<_> = uninit.into();
@ -166,7 +164,7 @@ impl<T: Scalar, R: DimName> Allocator<T, R, Dynamic> for DefaultAllocator {
#[inline]
fn allocate_from_iterator<I: IntoIterator<Item = T>>(
nrows: R,
ncols: Dynamic,
ncols: Dyn,
iter: I,
) -> Self::Buffer {
let it = iter.into_iter();
@ -215,20 +213,20 @@ where
}
}
// Static × Static -> Dynamic × Any
// Static × Static -> Dyn × Any
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, CTo, const RFROM: usize, const CFROM: usize>
Reallocator<T, Const<RFROM>, Const<CFROM>, Dynamic, CTo> for DefaultAllocator
Reallocator<T, Const<RFROM>, Const<CFROM>, Dyn, CTo> for DefaultAllocator
where
CTo: Dim,
{
#[inline]
unsafe fn reallocate_copy(
rto: Dynamic,
rto: Dyn,
cto: CTo,
buf: ArrayStorage<T, RFROM, CFROM>,
) -> VecStorage<MaybeUninit<T>, Dynamic, CTo> {
let mut res = <Self as Allocator<T, Dynamic, CTo>>::allocate_uninit(rto, cto);
) -> VecStorage<MaybeUninit<T>, Dyn, CTo> {
let mut res = <Self as Allocator<T, Dyn, CTo>>::allocate_uninit(rto, cto);
let (rfrom, cfrom) = buf.shape();
@ -246,20 +244,20 @@ where
}
}
// Static × Static -> Static × Dynamic
// Static × Static -> Static × Dyn
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, RTo, const RFROM: usize, const CFROM: usize>
Reallocator<T, Const<RFROM>, Const<CFROM>, RTo, Dynamic> for DefaultAllocator
Reallocator<T, Const<RFROM>, Const<CFROM>, RTo, Dyn> for DefaultAllocator
where
RTo: DimName,
{
#[inline]
unsafe fn reallocate_copy(
rto: RTo,
cto: Dynamic,
cto: Dyn,
buf: ArrayStorage<T, RFROM, CFROM>,
) -> VecStorage<MaybeUninit<T>, RTo, Dynamic> {
let mut res = <Self as Allocator<T, RTo, Dynamic>>::allocate_uninit(rto, cto);
) -> VecStorage<MaybeUninit<T>, RTo, Dyn> {
let mut res = <Self as Allocator<T, RTo, Dyn>>::allocate_uninit(rto, cto);
let (rfrom, cfrom) = buf.shape();
@ -279,60 +277,58 @@ where
// All conversion from a dynamic buffer to a dynamic buffer.
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, CFrom: Dim, CTo: Dim> Reallocator<T, Dynamic, CFrom, Dynamic, CTo>
for DefaultAllocator
{
impl<T: Scalar, CFrom: Dim, CTo: Dim> Reallocator<T, Dyn, CFrom, Dyn, CTo> for DefaultAllocator {
#[inline]
unsafe fn reallocate_copy(
rto: Dynamic,
rto: Dyn,
cto: CTo,
buf: VecStorage<T, Dynamic, CFrom>,
) -> VecStorage<MaybeUninit<T>, Dynamic, CTo> {
buf: VecStorage<T, Dyn, CFrom>,
) -> VecStorage<MaybeUninit<T>, Dyn, CTo> {
let new_buf = buf.resize(rto.value() * cto.value());
VecStorage::new(rto, cto, new_buf)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, CFrom: Dim, RTo: DimName> Reallocator<T, Dynamic, CFrom, RTo, Dynamic>
impl<T: Scalar, CFrom: Dim, RTo: DimName> Reallocator<T, Dyn, CFrom, RTo, Dyn>
for DefaultAllocator
{
#[inline]
unsafe fn reallocate_copy(
rto: RTo,
cto: Dynamic,
buf: VecStorage<T, Dynamic, CFrom>,
) -> VecStorage<MaybeUninit<T>, RTo, Dynamic> {
cto: Dyn,
buf: VecStorage<T, Dyn, CFrom>,
) -> VecStorage<MaybeUninit<T>, RTo, Dyn> {
let new_buf = buf.resize(rto.value() * cto.value());
VecStorage::new(rto, cto, new_buf)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, RFrom: DimName, CTo: Dim> Reallocator<T, RFrom, Dynamic, Dynamic, CTo>
impl<T: Scalar, RFrom: DimName, CTo: Dim> Reallocator<T, RFrom, Dyn, Dyn, CTo>
for DefaultAllocator
{
#[inline]
unsafe fn reallocate_copy(
rto: Dynamic,
rto: Dyn,
cto: CTo,
buf: VecStorage<T, RFrom, Dynamic>,
) -> VecStorage<MaybeUninit<T>, Dynamic, CTo> {
buf: VecStorage<T, RFrom, Dyn>,
) -> VecStorage<MaybeUninit<T>, Dyn, CTo> {
let new_buf = buf.resize(rto.value() * cto.value());
VecStorage::new(rto, cto, new_buf)
}
}
#[cfg(any(feature = "std", feature = "alloc"))]
impl<T: Scalar, RFrom: DimName, RTo: DimName> Reallocator<T, RFrom, Dynamic, RTo, Dynamic>
impl<T: Scalar, RFrom: DimName, RTo: DimName> Reallocator<T, RFrom, Dyn, RTo, Dyn>
for DefaultAllocator
{
#[inline]
unsafe fn reallocate_copy(
rto: RTo,
cto: Dynamic,
buf: VecStorage<T, RFrom, Dynamic>,
) -> VecStorage<MaybeUninit<T>, RTo, Dynamic> {
cto: Dyn,
buf: VecStorage<T, RFrom, Dyn>,
) -> VecStorage<MaybeUninit<T>, RTo, Dyn> {
let new_buf = buf.resize(rto.value() * cto.value());
VecStorage::new(rto, cto, new_buf)
}

View File

@ -8,54 +8,69 @@ use std::fmt::Debug;
use std::ops::{Add, Div, Mul, Sub};
use typenum::{self, Diff, Max, Maximum, Min, Minimum, Prod, Quot, Sum, Unsigned};
#[cfg(feature = "rkyv-serialize")]
use rkyv::bytecheck;
#[cfg(feature = "serde-serialize-no-std")]
use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// Dim of dynamically-sized algebraic entities.
#[derive(Clone, Copy, Eq, PartialEq, Debug)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
pub struct Dynamic {
value: usize,
}
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
)]
#[cfg_attr(
feature = "rkyv-serialize",
archive_attr(derive(bytecheck::CheckBytes))
)]
pub struct Dyn(pub usize);
impl Dynamic {
#[deprecated(note = "use Dyn instead.")]
pub type Dynamic = Dyn;
impl Dyn {
/// A dynamic size equal to `value`.
#[inline]
#[deprecated(note = "use Dyn(value) instead.")]
pub const fn new(value: usize) -> Self {
Self { value }
Self(value)
}
}
#[cfg(feature = "serde-serialize-no-std")]
impl Serialize for Dynamic {
impl Serialize for Dyn {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.value.serialize(serializer)
self.0.serialize(serializer)
}
}
#[cfg(feature = "serde-serialize-no-std")]
impl<'de> Deserialize<'de> for Dynamic {
impl<'de> Deserialize<'de> for Dyn {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
usize::deserialize(deserializer).map(|x| Dynamic { value: x })
usize::deserialize(deserializer).map(|x| Dyn(x))
}
}
/// Trait implemented by `Dynamic`.
/// Trait implemented by `Dyn`.
pub trait IsDynamic {}
/// Trait implemented by `Dynamic` and type-level integers different from `U1`.
/// Trait implemented by `Dyn` and type-level integers different from `U1`.
pub trait IsNotStaticOne {}
impl IsDynamic for Dynamic {}
impl IsNotStaticOne for Dynamic {}
impl IsDynamic for Dyn {}
impl IsNotStaticOne for Dyn {}
/// Trait implemented by any type that can be used as a dimension. This includes type-level
/// integers and `Dynamic` (for dimensions not known at compile-time).
/// integers and `Dyn` (for dimensions not known at compile-time).
///
/// # Safety
///
/// Hoists integers to the type level, including binary operations.
pub unsafe trait Dim: Any + Debug + Copy + PartialEq + Send + Sync {
#[inline(always)]
fn is<D: Dim>() -> bool {
@ -63,7 +78,7 @@ pub unsafe trait Dim: Any + Debug + Copy + PartialEq + Send + Sync {
}
/// Gets the compile-time value of `Self`. Returns `None` if it is not known, i.e., if `Self =
/// Dynamic`.
/// Dyn`.
fn try_to_usize() -> Option<usize>;
/// Gets the run-time value of `self`. For type-level integers, this is the same as
@ -75,7 +90,7 @@ pub unsafe trait Dim: Any + Debug + Copy + PartialEq + Send + Sync {
fn from_usize(dim: usize) -> Self;
}
unsafe impl Dim for Dynamic {
unsafe impl Dim for Dyn {
#[inline]
fn try_to_usize() -> Option<usize> {
None
@ -83,30 +98,30 @@ unsafe impl Dim for Dynamic {
#[inline]
fn from_usize(dim: usize) -> Self {
Self::new(dim)
Self(dim)
}
#[inline]
fn value(&self) -> usize {
self.value
self.0
}
}
impl Add<usize> for Dynamic {
type Output = Dynamic;
impl Add<usize> for Dyn {
type Output = Dyn;
#[inline]
fn add(self, rhs: usize) -> Self {
Self::new(self.value + rhs)
Self(self.0 + rhs)
}
}
impl Sub<usize> for Dynamic {
type Output = Dynamic;
impl Sub<usize> for Dyn {
type Output = Dyn;
#[inline]
fn sub(self, rhs: usize) -> Self {
Self::new(self.value - rhs)
Self(self.0 - rhs)
}
}
@ -144,22 +159,22 @@ macro_rules! dim_ops(
}
}
impl<D: Dim> $DimOp<D> for Dynamic {
type Output = Dynamic;
impl<D: Dim> $DimOp<D> for Dyn {
type Output = Dyn;
#[inline]
fn $op(self, other: D) -> Dynamic {
Dynamic::new($op_path(self.value, other.value()))
fn $op(self, other: D) -> Dyn {
Dyn($op_path(self.value(), other.value()))
}
}
// TODO: use Const<T> instead of D: DimName?
impl<D: DimName> $DimOp<Dynamic> for D {
type Output = Dynamic;
impl<D: DimName> $DimOp<Dyn> for D {
type Output = Dyn;
#[inline]
fn $op(self, other: Dynamic) -> Dynamic {
Dynamic::new($op_path(self.value(), other.value))
fn $op(self, other: Dyn) -> Dyn {
Dyn($op_path(self.value(), other.value()))
}
}
@ -198,7 +213,12 @@ dim_ops!(
);
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "cuda", derive(cust_core::DeviceCopy))]
#[cfg_attr(
feature = "rkyv-serialize-no-std",
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize),
archive(as = "Self")
)]
#[cfg_attr(feature = "rkyv-serialize", derive(bytecheck::CheckBytes))]
pub struct Const<const R: usize>;
/// Trait implemented exclusively by type-level integers.
@ -233,37 +253,6 @@ impl<'de, const D: usize> Deserialize<'de> for Const<D> {
}
}
#[cfg(feature = "rkyv-serialize-no-std")]
mod rkyv_impl {
use super::Const;
use rkyv::{Archive, Deserialize, Fallible, Serialize};
impl<const R: usize> Archive for Const<R> {
type Archived = Self;
type Resolver = ();
fn resolve(
&self,
_: usize,
_: Self::Resolver,
_: &mut core::mem::MaybeUninit<Self::Archived>,
) {
}
}
impl<S: Fallible + ?Sized, const R: usize> Serialize<S> for Const<R> {
fn serialize(&self, _: &mut S) -> Result<Self::Resolver, S::Error> {
Ok(())
}
}
impl<D: Fallible + ?Sized, const R: usize> Deserialize<Self, D> for Const<R> {
fn deserialize(&self, _: &mut D) -> Result<Self, D::Error> {
Ok(Const)
}
}
}
pub trait ToConst {
type Const: DimName;
}
@ -273,14 +262,17 @@ pub trait ToTypenum {
}
unsafe impl<const T: usize> Dim for Const<T> {
#[inline]
fn try_to_usize() -> Option<usize> {
Some(T)
}
#[inline]
fn value(&self) -> usize {
T
}
#[inline]
fn from_usize(dim: usize) -> Self {
assert_eq!(dim, T);
Self
@ -324,6 +316,11 @@ macro_rules! from_to_typenum (
}
impl IsNotStaticOne for $D { }
/// The constant dimension
#[doc = stringify!($VAL)]
/// .
pub const $D: $D = Const::<$VAL>;
)*}
);
@ -337,3 +334,7 @@ from_to_typenum!(
U111, 111; U112, 112; U113, 113; U114, 114; U115, 115; U116, 116; U117, 117; U118, 118; U119, 119; U120, 120; U121, 121; U122, 122; U123, 123; U124, 124; U125, 125; U126, 126;
U127, 127
);
/// The constant dimension 1.
// Note: We add U1 separately since it's not covered by the from_to_typenum! macro.
pub const U1: U1 = Const::<1>;

Some files were not shown because too many files have changed in this diff Show More