diff --git a/.cargo/config b/.cargo/config.toml similarity index 100% rename from .cargo/config rename to .cargo/config.toml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..58a4926 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,28 @@ +name: build +on: + merge_group: + pull_request: + push: +env: + CARGO_TERM_COLOR: always +jobs: + default: + runs-on: ubuntu-latest + steps: + - name: checkout + uses: actions/checkout@v3 + - name: toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: stable + components: rustfmt, rust-docs, clippy + - name: test + run: cargo test + - name: clippy + run: cargo clippy --tests --examples -- -D clippy::all -D clippy::pedantic -D clippy::nursery + - name: doc + run: cargo doc + - name: tex + run: cargo tex + - name: fmt + run: cargo fmt --check diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 46fae61..0000000 --- a/.travis.yml +++ /dev/null @@ -1,10 +0,0 @@ -language: rust -env: FEATURES="" -matrix: - include: - - rust: stable - - rust: beta - - rust: nightly -script: - - cargo build --verbose --features "$FEATURES" - - cargo test --verbose --features "$FEATURES" diff --git a/Cargo.toml b/Cargo.toml index c0683cd..696bfe6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "nalgebra-spacetime" -version = "0.2.4" +version = "0.3.0" authors = ["Rouven Spreckels "] -edition = "2018" +edition = "2021" description = "Spacetime Extension for nalgebra" -documentation = "https://doc.qu1x.dev/nalgebra-spacetime" +documentation = "https://docs.rs/nalgebra-spacetime" repository = "https://github.com/qu1x/nalgebra-spacetime" readme = "README.md" -license = "BSD-3-Clause" +license = "MIT OR Apache-2.0" keywords = [ "lorentzian-space", "minkowski-space", @@ -25,16 +25,13 @@ include = [ "Cargo.toml", "README.md", "RELEASES.md", - "LICENSE.md", + "LICENSES/*.md", ] [package.metadata.docs.rs] rustdoc-args = [ "--html-in-header", "katex.html" ] -[badges] -travis-ci = { repository = "qu1x/nalgebra-spacetime" } - [dependencies] -nalgebra = { version = "0.25", features = ["rand"] } -num-traits = "0.2" -approx = { version = "0.4", default-features = false } +nalgebra = { version = "0.32.4", features = ["rand"] } +num-traits = "0.2.18" +approx = { version = "0.5.1", default-features = false } diff --git a/LICENSES/Apache-2.0 b/LICENSES/Apache-2.0 new file mode 100644 index 0000000..1b5ec8b --- /dev/null +++ b/LICENSES/Apache-2.0 @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS diff --git a/LICENSES/MIT b/LICENSES/MIT new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/LICENSES/MIT @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index bfea901..15536d0 100644 --- a/README.md +++ b/README.md @@ -4,24 +4,19 @@ Spacetime Extension for [nalgebra] [nalgebra]: https://nalgebra.org -[![Build Status][]](https://travis-ci.org/qu1x/nalgebra-spacetime) +[![Build][]](https://github.com/qu1x/nalgebra-spacetime/actions/workflows/build.yml) +[![Documentation][]](https://docs.rs/nalgebra-spacetime) [![Downloads][]](https://crates.io/crates/nalgebra-spacetime) -[![Rust][]](https://www.rust-lang.org) [![Version][]](https://crates.io/crates/nalgebra-spacetime) -[![Documentation][]](https://doc.qu1x.dev/nalgebra-spacetime) -[![License][]](https://opensource.org/licenses/BSD-3-Clause) +[![Rust][]](https://www.rust-lang.org) +[![License][]](https://opensource.org/licenses) -[Build Status]: https://travis-ci.org/qu1x/nalgebra-spacetime.svg +[Build]: https://github.com/qu1x/nalgebra-spacetime/actions/workflows/build.yml/badge.svg +[Documentation]: https://docs.rs/nalgebra-spacetime/badge.svg [Downloads]: https://img.shields.io/crates/d/nalgebra-spacetime.svg -[Rust]: https://img.shields.io/badge/rust-stable-brightgreen.svg [Version]: https://img.shields.io/crates/v/nalgebra-spacetime.svg -[Documentation]: https://docs.rs/nalgebra-spacetime/badge.svg -[License]: https://img.shields.io/crates/l/nalgebra-spacetime.svg - -API Documentation with KaTeX: [stable] | [master] - -[stable]: https://docs.rs/nalgebra-spacetime -[master]: https://doc.qu1x.dev/nalgebra-spacetime +[Rust]: https://img.shields.io/badge/rust-stable-brightgreen.svg +[License]: https://img.shields.io/badge/License-MIT%20OR%20Apache--2.0-blue.svg # Present Features @@ -40,27 +35,34 @@ API Documentation with KaTeX: [stable] | [master] * Categorize `Rotation4`/`PureBoost4`/`...` as `Boost4`/`...`. * Wigner `rotation()` and `axis_angle()` of an already-composed `Boost4`. * Distinguish pre/post-rotation and active/passive `Boost4` compositions. - * Spacetime algebra (STA) as special case of `CliffordN` space. # Pseudo-local Documentation Builds ```sh # Build and open documentation inclusive dependencies. cargo doc --open -# Update any source file, then regenerate this crate's documentation with KaTeX. +# Rebuild this crate's documentation with KaTeX. cargo tex # Refresh opened documentation. ``` -With `cargo tex` defined in [.cargo/config](.cargo/config). Note that navigating -the documentation requires web access as KaTeX is embedded via remote CDN. +With `cargo tex` defined in [.cargo/config](.cargo/config). Note that navigating the documentation +requires web access as KaTeX is embedded via remote CDN. + +# License + +Copyright © 2020,2021,2024 Rouven Spreckels + +This project is licensed under either of -## License + * Apache License, Version 2.0, ([LICENSES/Apache-2.0](LICENSES/Apache-2.0) or + https://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSES/MIT](LICENSES/MIT) or https://opensource.org/licenses/MIT) -[BSD-3-Clause](LICENSE.md) +at your option. -## Contribution +# Contribution -Unless you explicitly state otherwise, any contribution intentionally submitted -for inclusion in the works by you shall be licensed as above, without any -additional terms or conditions. +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in +this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without +any additional terms or conditions. diff --git a/RELEASES.md b/RELEASES.md index 95ccd3b..33a459d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,8 @@ +# Version 0.3.0 (2024-02-21) + + * Update dependencies. + * Change license to `MIT OR Apache-2.0`. + # Version 0.2.4 (2021-03-06) * Update `nalgebra`. diff --git a/katex.html b/katex.html index d4883ec..326976a 100644 --- a/katex.html +++ b/katex.html @@ -1,12 +1,12 @@ - - - + + + diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..36af38c --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,3 @@ +hard_tabs = true +format_code_in_doc_comments = true +max_width = 100 diff --git a/src/lib.rs b/src/lib.rs index 91d4051..ccc18d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,42 +13,34 @@ //! * Inertial [`FrameN`] of reference holding boost parameters. //! * Lorentz boost as [`LorentzianN::new_boost`] matrix. //! * Direct Lorentz [`LorentzianN::boost`] to [`FrameN::compose`] velocities. -//! * Wigner [`FrameN::rotation`] and [`FrameN::axis_angle`] between -//! to-be-composed boosts. +//! * Wigner [`FrameN::rotation`] and [`FrameN::axis_angle`] between to-be-composed boosts. //! //! # Future Features //! //! * `Event4`/`Velocity4`/`Momentum4`/`...` equivalents of `Point4`/`...`. //! * Categorize `Rotation4`/`PureBoost4`/`...` as `Boost4`/`...`. -//! * Wigner [`FrameN::rotation`] and [`FrameN::axis_angle`] of an -//! already-composed `Boost4`. +//! * Wigner [`FrameN::rotation`] and [`FrameN::axis_angle`] of an already-composed `Boost4`. //! * Distinguish pre/post-rotation and active/passive `Boost4` compositions. -//! * Spacetime algebra (STA) as special case of `CliffordN` space. #![forbid(unsafe_code)] #![forbid(missing_docs)] +#![allow(clippy::doc_markdown)] +#![allow(clippy::type_complexity)] -use std::ops::{Neg, Add, Sub}; +use approx::{abs_diff_eq, AbsDiffEq}; use nalgebra::{ - Unit, VectorN, Vector3, Matrix, MatrixMN, Matrix4, Rotation3, - VectorSliceN, MatrixSliceMN, MatrixSliceMutMN, - Scalar, SimdRealField, - Dim, DimName, DimNameSub, DimNameDiff, + base::allocator::Allocator, base::dimension::{U1, U2, U3, U4}, constraint::{ + AreMultipliable, DimEq, SameDimension, SameNumberOfColumns, SameNumberOfRows, ShapeConstraint, - SameDimension, - SameNumberOfRows, - SameNumberOfColumns, - AreMultipliable, - DimEq, }, - storage::{Storage, StorageMut, Owned}, - DefaultAllocator, base::allocator::Allocator, + storage::{Owned, RawStorage, RawStorageMut, Storage, StorageMut}, + DefaultAllocator, Dim, DimName, DimNameDiff, DimNameSub, Matrix, Matrix4, MatrixView, + MatrixViewMut, OMatrix, OVector, Rotation3, Scalar, SimdRealField, Unit, Vector3, VectorView, }; -use num_traits::{sign::Signed, real::Real}; -use approx::{AbsDiffEq, abs_diff_eq}; -use LightCone::*; +use num_traits::{real::Real, sign::Signed}; +use std::ops::{Add, Neg, Sub}; /// Extension for $n$-dimensional Lorentzian space $\R^{-,+} = \R^{1,n-1}$ with /// metric signature in spacelike sign convention. @@ -75,26 +67,24 @@ where /// /// Avoid matrix multiplication by preferring: /// - /// * [`Self::dual`], [`Self::r_dual`] or [`Self::c_dual`] and their - /// in-place counterparts + /// * [`Self::dual`], [`Self::r_dual`] or [`Self::c_dual`] and their in-place counterparts /// * [`Self::dual_mut`], [`Self::r_dual_mut`] or [`Self::c_dual_mut`]. /// - /// The spacelike sign convention $\R^{-,+} = \R^{1,n-1}$ requires less - /// negations than its timelike alternative $\R^{+,-} = \R^{1,n-1}$. In four - /// dimensions or Minkowski space $\R^{-,+} = \R^{1,3}$ it requires: + /// The spacelike sign convention $\R^{-,+} = \R^{1,n-1}$ requires less negations than its + /// timelike alternative $\R^{+,-} = \R^{1,n-1}$. In four dimensions or Minkowski space + /// $\R^{-,+} = \R^{1,3}$ it requires: /// /// * $n - 2 = 2$ less for degree-1 tensors, and /// * $n (n - 2) = 8$ less for one index of degree-2 tensors, but /// * $0$ less for two indices of degree-2 tensors. /// - /// Choosing the component order of $\R^{-,+} = \R^{1,n-1}$ over - /// $\R^{+,-} = \R^{n-1,1}$ identifies the time component of $x^\mu$ as - /// $x^0$ in compliance with the convention of identifying spatial - /// components $x^i$ with Latin alphabet indices starting from $i=1$. + /// Choosing the component order of $\R^{-,+} = \R^{1,n-1}$ over $\R^{+,-} = \R^{n-1,1}$ + /// identifies the time component of $x^\mu$ as $x^0$ in compliance with the convention of + /// identifying spatial components $x^i$ with Latin alphabet indices starting from $i=1$. /// ``` - /// use nalgebra::{Vector4, Matrix4}; - /// use nalgebra_spacetime::LorentzianN; /// use approx::assert_ulps_eq; + /// use nalgebra::{Matrix4, Vector4}; + /// use nalgebra_spacetime::LorentzianN; /// /// let eta = Matrix4::::metric(); /// let sc = Vector4::new(-1.0, 1.0, 1.0, 1.0); @@ -110,6 +100,7 @@ where /// assert_ulps_eq!(f.r_dual(), eta * f); /// assert_ulps_eq!(f.c_dual(), f * eta); /// ``` + #[must_use] fn metric() -> Self where ShapeConstraint: SameDimension; @@ -117,16 +108,19 @@ where /// Raises/Lowers *all* of its degree-1/degree-2 tensor indices. /// /// Negates the appropriate components avoiding matrix multiplication. + #[must_use] fn dual(&self) -> Self; /// Raises/Lowers its degree-1/degree-2 *row* tensor index. /// /// Prefer [`Self::dual`] over `self.r_dual().c_dual()` to half negations. + #[must_use] fn r_dual(&self) -> Self; /// Raises/Lowers its degree-1/degree-2 *column* tensor index. /// /// Prefer [`Self::dual`] over `self.r_dual().c_dual()` to half negations. + #[must_use] fn c_dual(&self) -> Self; /// Raises/Lowers *all* of its degree-1/degree-2 tensor indices *in-place*. @@ -142,16 +136,15 @@ where /// Raises/Lowers its degree-1/degree-2 *column* tensor index *in-place*. /// - /// Prefer [`Self::dual`] over `self.r_dual_mut().c_dual_mut()` to half - /// negations. + /// Prefer [`Self::dual`] over `self.r_dual_mut().c_dual_mut()` to half negations. fn c_dual_mut(&mut self); /// Lorentzian matrix multiplication of degree-1/degree-2 tensors. /// - /// Equals `self.c_dual() * rhs`, the metric contraction of its *column* - /// index with `rhs`'s *row* index. - fn contr(&self, rhs: &Matrix) - -> MatrixMN + /// Equals `self.c_dual() * rhs`, the metric contraction of its *column* index with `rhs`'s + /// *row* index. + #[must_use] + fn contr(&self, rhs: &Matrix) -> OMatrix where R2: Dim, C2: Dim, @@ -161,10 +154,10 @@ where /// Same as [`Self::contr`] but with transposed tensor indices. /// - /// Equals `self.r_dual().tr_mul(rhs)`, the metric contraction of its - /// *transposed row* index with `rhs`'s *row* index. - fn tr_contr(&self, rhs: &Matrix) - -> MatrixMN + /// Equals `self.r_dual().tr_mul(rhs)`, the metric contraction of its *transposed row* index + /// with `rhs`'s *row* index. + #[must_use] + fn tr_contr(&self, rhs: &Matrix) -> OMatrix where R2: Dim, C2: Dim, @@ -185,6 +178,7 @@ where /// * relativistic dot product, /// * Lorentz scalar, invariant under Lorentz transformations, or /// * spacetime interval between two events, see [`Self::interval`]. + #[must_use] fn scalar(&self, rhs: &Matrix) -> N where R2: Dim, @@ -195,6 +189,7 @@ where /// Same as [`Self::scalar`] but with transposed tensor indices. /// /// Equals `self.dual().tr_dot(rhs)`. + #[must_use] fn tr_scalar(&self, rhs: &Matrix) -> N where R2: Dim, @@ -207,6 +202,7 @@ where /// Equals `self.scalar(self).neg().sqrt()`. /// /// If spacelike, returns *NaN* or panics if `N` doesn't support it. + #[must_use] fn timelike_norm(&self) -> N; /// Lorentzian norm of spacelike degree-1/degree-2 tensors. @@ -214,15 +210,16 @@ where /// Equals `self.scalar(self).sqrt()`. /// /// If timelike, returns *NaN* or panics if `N` doesn't support it. + #[must_use] fn spacelike_norm(&self) -> N; /// Spacetime interval between two events and region of `self`'s light cone. /// - /// Same as [`Self::interval_fn`] but with [`AbsDiffEq::default_epsilon`] as - /// in: + /// Same as [`Self::interval_fn`] but with [`AbsDiffEq::default_epsilon`] as in: /// /// * `is_present = |time| abs_diff_eq!(time, N::zero())`, and /// * `is_lightlike = |interval| abs_diff_eq!(interval, N::zero())`. + #[must_use] fn interval(&self, rhs: &Self) -> (N, LightCone) where N: AbsDiffEq, @@ -230,22 +227,19 @@ where /// Spacetime interval between two events and region of `self`'s light cone. /// - /// Equals `(rhs - self).scalar(&(rhs - self))` where `self` is subtracted - /// from `rhs` to depict `rhs` in `self`'s light cone. + /// Equals `(rhs - self).scalar(&(rhs - self))` where `self` is subtracted from `rhs` to depict + /// `rhs` in `self`'s light cone. /// /// Requires you to approximate when `N` equals `N::zero()` via: /// /// * `is_present` for the time component of `rhs - self`, and /// * `is_lightlike` for the interval. /// - /// Their signs are only evaluated in the `false` branches of `is_present` - /// and `is_lightlike`. + /// Their signs are only evaluated in the `false` branches of `is_present` and `is_lightlike`. /// - /// See [`Self::interval`] for using defaults and [`approx`] for further - /// details. - fn interval_fn(&self, rhs: &Self, - is_present: P, is_lightlike: L) - -> (N, LightCone) + /// See [`Self::interval`] for using defaults and [`approx`] for further details. + #[must_use] + fn interval_fn(&self, rhs: &Self, is_present: P, is_lightlike: L) -> (N, LightCone) where ShapeConstraint: DimEq, P: Fn(N) -> bool, @@ -256,15 +250,15 @@ where /// \gdef \Lmu {\Lambda^{\mu'}\_{\phantom {\mu'} \mu}} /// \gdef \Lnu {(\Lambda^T)\_\nu^{\phantom \nu \nu'}} /// $ - /// Lorentz transformation $\Lmu(\hat u, \zeta)$ boosting degree-1/degree-2 - /// tensors to inertial `frame` of reference. + /// Lorentz transformation $\Lmu(\hat u, \zeta)$ boosting degree-1/degree-2 tensors to inertial + /// `frame` of reference. /// /// $$ /// \Lmu(\hat u, \zeta) = I - \sinh \zeta (\uk) + (\cosh \zeta - 1) (\uk)^2 /// $$ /// - /// Where $\uk$ is the generator of the boost along $\hat{u}$ with its - /// spatial components $(u^1, \dots, u^{n-1})$: + /// Where $\uk$ is the generator of the boost along $\hat{u}$ with its spatial componentsi + /// $(u^1, \dots, u^{n-1})$: /// /// $$ /// \uk = \begin{pmatrix} @@ -280,36 +274,37 @@ where /// x^{\mu'} = \Lmu x^\mu /// $$ /// - /// Boosts degree-2 tensors by multiplying it from the left and its - /// transpose (symmetric for pure boosts) from the right: + /// Boosts degree-2 tensors by multiplying it from the left and its transpose (symmetric for + /// pure boosts) from the right: /// /// $$ /// F^{\mu' \nu'} = \Lmu F^{\mu \nu} \Lnu /// $$ /// /// ``` - /// use nalgebra::{Vector3, Vector4, Matrix4}; - /// use nalgebra_spacetime::{LorentzianN, Frame4}; /// use approx::assert_ulps_eq; + /// use nalgebra::{Matrix4, Vector3, Vector4}; + /// use nalgebra_spacetime::{Frame4, LorentzianN}; /// /// let event = Vector4::new_random(); /// let frame = Frame4::from_beta(Vector3::new(0.3, -0.4, 0.6)); /// let boost = Matrix4::new_boost(&frame); /// assert_ulps_eq!(boost * event, event.boost(&frame), epsilon = 1e-14); /// ``` + #[must_use] fn new_boost(frame: &FrameN) -> Self where D: DimNameSub, ShapeConstraint: AreMultipliable + DimEq, DefaultAllocator: Allocator>; - /// Boosts this degree-1 tensor $x^\mu$ to inertial `frame` of reference - /// along $\hat u$ with $\zeta$. + /// Boosts this degree-1 tensor $x^\mu$ to inertial `frame` of reference along $\hat u$ with + /// $\zeta$. /// /// ``` - /// use nalgebra::{Vector3, Vector4}; - /// use nalgebra_spacetime::{LorentzianN, Frame4}; /// use approx::assert_ulps_eq; + /// use nalgebra::{Vector3, Vector4}; + /// use nalgebra_spacetime::{Frame4, LorentzianN}; /// /// let muon_lifetime_at_rest = Vector4::new(2.2e-6, 0.0, 0.0, 0.0); /// let muon_frame = Frame4::from_axis_beta(Vector3::z_axis(), 0.9952); @@ -319,17 +314,22 @@ where /// ``` /// /// See `boost_mut()` for further details. + #[must_use] fn boost(&self, frame: &FrameN) -> Self where + R: DimNameSub, D: DimNameSub, - ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + ShapeConstraint: SameNumberOfRows + + SameNumberOfColumns + + DimEq<>::Output, >::Output> + + SameNumberOfRows<>::Output, >::Output>, DefaultAllocator: Allocator>; /// $ /// \gdef \xu {(\vec x \cdot \hat u)} /// $ - /// Boosts this degree-1 tensor $x^\mu$ to inertial `frame` of reference - /// along $\hat u$ with $\zeta$ *in-place*. + /// Boosts this degree-1 tensor $x^\mu$ to inertial `frame` of reference along $\hat u$ with + /// $\zeta$ *in-place*. /// /// $$ /// \begin{pmatrix} @@ -342,9 +342,9 @@ where /// $$ /// /// ``` + /// use approx::assert_ulps_eq; /// use nalgebra::Vector4; /// use nalgebra_spacetime::LorentzianN; - /// use approx::assert_ulps_eq; /// /// // Arbitrary timelike four-momentum. /// let mut momentum = Vector4::new(24.3, 5.22, 16.8, 9.35); @@ -364,18 +364,24 @@ where /// ``` fn boost_mut(&mut self, frame: &FrameN) where + R: DimNameSub, D: DimNameSub, - ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + ShapeConstraint: SameNumberOfRows + + SameNumberOfColumns + + DimEq<>::Output, >::Output> + + SameNumberOfRows<>::Output, >::Output>, DefaultAllocator: Allocator>; /// Velocity $u^\mu$ of inertial `frame` of reference. - fn new_velocity(frame: &FrameN) -> VectorN + #[must_use] + fn new_velocity(frame: &FrameN) -> OVector where D: DimNameSub, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, DefaultAllocator: Allocator> + Allocator; /// Inertial frame of reference of this velocity $u^\mu$. + #[must_use] fn frame(&self) -> FrameN where R: DimNameSub, @@ -383,8 +389,8 @@ where DefaultAllocator: Allocator>; /// From `temporal` and `spatial` spacetime split. - fn from_split(temporal: &N, spatial: &VectorN>) - -> VectorN + #[must_use] + fn from_split(temporal: &N, spatial: &OVector>) -> OVector where D: DimNameSub, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, @@ -393,7 +399,8 @@ where StorageMut; /// Spacetime split into [`Self::temporal`] and [`Self::spatial`]. - fn split(&self) -> (&N, MatrixSliceMN, C, U1, R>) + #[must_use] + fn split(&self) -> (&N, MatrixView, C, U1, R>) where R: DimNameSub, ShapeConstraint: DimEq, @@ -405,9 +412,9 @@ where /// [`Self::spatial_mut`]. /// /// ``` + /// use approx::assert_ulps_eq; /// use nalgebra::Vector4; /// use nalgebra_spacetime::LorentzianN; - /// use approx::assert_ulps_eq; /// /// let mut spacetime = Vector4::new(1.0, 2.0, 3.0, 4.0); /// let (temporal, mut spatial) = spacetime.split_mut(); @@ -417,8 +424,7 @@ where /// spatial[2] += 4.0; /// assert_ulps_eq!(spacetime, Vector4::new(2.0, 4.0, 6.0, 8.0)); /// ``` - fn split_mut(&mut self) - -> (&mut N, MatrixSliceMutMN, C>) + fn split_mut(&mut self) -> (&mut N, MatrixViewMut, C>) where R: DimNameSub, ShapeConstraint: DimEq, @@ -427,6 +433,7 @@ where Storage; /// Temporal component. + #[must_use] fn temporal(&self) -> &N where R: DimNameSub, @@ -439,8 +446,8 @@ where ShapeConstraint: DimEq; /// Spatial components. - fn spatial(&self) - -> MatrixSliceMN, C, U1, R> + #[must_use] + fn spatial(&self) -> MatrixView, C, U1, R> where R: DimNameSub, ShapeConstraint: DimEq, @@ -449,8 +456,7 @@ where Storage; /// Mutable spatial components. - fn spatial_mut(&mut self) - -> MatrixSliceMutMN, C, U1, R> + fn spatial_mut(&mut self) -> MatrixViewMut, C, U1, R> where R: DimNameSub, ShapeConstraint: DimEq, @@ -459,10 +465,10 @@ where StorageMut; } -impl LorentzianN for MatrixMN +impl LorentzianN for OMatrix where N: SimdRealField + Signed + Real, - R: DimName, + R: DimName + DimNameSub, C: DimName, DefaultAllocator: Allocator, { @@ -531,8 +537,7 @@ where } #[inline] - fn contr(&self, rhs: &Matrix) - -> MatrixMN + fn contr(&self, rhs: &Matrix) -> OMatrix where R2: Dim, C2: Dim, @@ -544,8 +549,7 @@ where } #[inline] - fn tr_contr(&self, rhs: &Matrix) - -> MatrixMN + fn tr_contr(&self, rhs: &Matrix) -> OMatrix where R2: Dim, C2: Dim, @@ -594,15 +598,14 @@ where N: AbsDiffEq, ShapeConstraint: DimEq, { - self.interval_fn(rhs, + self.interval_fn( + rhs, |time| abs_diff_eq!(time, N::zero()), |interval| abs_diff_eq!(interval, N::zero()), ) } - fn interval_fn(&self, rhs: &Self, - is_present: P, is_lightlike: L) - -> (N, LightCone) + fn interval_fn(&self, rhs: &Self, is_present: P, is_lightlike: L) -> (N, LightCone) where ShapeConstraint: DimEq, P: Fn(N) -> bool, @@ -613,18 +616,18 @@ where let interval = difference.scalar(&difference); let light_cone = if is_lightlike(interval) { if is_present(time) { - Origin + LightCone::Origin + } else if time.is_sign_positive() { + LightCone::LightlikeFuture } else { - if time.is_sign_positive() - { LightlikeFuture } else { LightlikePast } + LightCone::LightlikePast } + } else if interval.is_sign_positive() || is_present(time) { + LightCone::Spacelike + } else if time.is_sign_positive() { + LightCone::TimelikeFuture } else { - if interval.is_sign_positive() || is_present(time) { - Spacelike - } else { - if time.is_sign_positive() - { TimelikeFuture } else { TimelikePast } - } + LightCone::TimelikePast }; (interval, light_cone) } @@ -635,11 +638,15 @@ where ShapeConstraint: AreMultipliable + DimEq, DefaultAllocator: Allocator>, { - let &FrameN { zeta_cosh, zeta_sinh, ref axis } = frame; + let &FrameN { + zeta_cosh, + zeta_sinh, + ref axis, + } = frame; let mut b = Self::zeros(); for (i, u) in axis.iter().enumerate() { - b[(i + 1, 0)] = u.inlined_clone(); - b[(0, i + 1)] = u.inlined_clone(); + b[(i + 1, 0)] = *u; + b[(0, i + 1)] = *u; } let uk = b.clone_owned(); b.gemm(zeta_cosh - N::one(), &uk, &uk, -zeta_sinh); @@ -652,8 +659,12 @@ where #[inline] fn boost(&self, frame: &FrameN) -> Self where + R: DimNameSub, D: DimNameSub, - ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + ShapeConstraint: SameNumberOfRows + + SameNumberOfColumns + + DimEq<>::Output, >::Output> + + SameNumberOfRows<>::Output, >::Output>, DefaultAllocator: Allocator>, { let mut v = self.clone_owned(); @@ -663,21 +674,30 @@ where fn boost_mut(&mut self, frame: &FrameN) where + R: DimNameSub, D: DimNameSub, - ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, + ShapeConstraint: SameNumberOfRows + + SameNumberOfColumns + + DimEq<>::Output, >::Output> + + SameNumberOfRows<>::Output, >::Output>, DefaultAllocator: Allocator>, { - let &FrameN { zeta_cosh, zeta_sinh, ref axis } = frame; + let &FrameN { + zeta_cosh, + zeta_sinh, + ref axis, + } = frame; let u = axis.as_ref(); let a = self[0]; - let zu = self.fixed_rows::>(1).dot(u); + let (rows, _cols) = self.shape_generic(); + let zu = self.rows_generic(1, rows.sub(U1)).dot(u); self[0] = zeta_cosh * a - zeta_sinh * zu; - let mut z = self.fixed_rows_mut::>(1); + let mut z = self.rows_generic_mut(1, rows.sub(U1)); z += u * ((zeta_cosh - N::one()) * zu - zeta_sinh * a); } #[inline] - fn new_velocity(frame: &FrameN) -> VectorN + fn new_velocity(frame: &FrameN) -> OVector where D: DimNameSub, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, @@ -697,8 +717,7 @@ where } #[inline] - fn from_split(temporal: &N, spatial: &VectorN>) - -> VectorN + fn from_split(temporal: &N, spatial: &OVector>) -> OVector where D: DimNameSub, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, @@ -706,14 +725,14 @@ where >::Buffer: StorageMut, { - let mut v = VectorN::::zeros(); + let mut v = OVector::::zeros(); *v.temporal_mut() = *temporal; v.spatial_mut().copy_from(spatial); v } #[inline] - fn split(&self) -> (&N, MatrixSliceMN, C, U1, R>) + fn split(&self) -> (&N, MatrixView, C, U1, R>) where R: DimNameSub, ShapeConstraint: DimEq, @@ -725,8 +744,7 @@ where } #[inline] - fn split_mut(&mut self) - -> (&mut N, MatrixSliceMutMN, C>) + fn split_mut(&mut self) -> (&mut N, MatrixViewMut, C>) where R: DimNameSub, ShapeConstraint: DimEq, @@ -737,7 +755,7 @@ where let (temporal, spatial) = self.as_mut_slice().split_at_mut(1); ( temporal.get_mut(0).unwrap(), - MatrixSliceMutMN::, C>::from_slice(spatial), + MatrixViewMut::, C>::from_slice(spatial), ) } @@ -760,33 +778,33 @@ where } #[inline] - fn spatial(&self) - -> MatrixSliceMN, C, U1, R> + fn spatial(&self) -> MatrixView, C, U1, R> where R: DimNameSub, ShapeConstraint: DimEq, >::Buffer: - Storage, + RawStorage, { - self.fixed_slice::, C>(1, 0) + let (rows, _cols) = self.shape_generic(); + self.rows_generic(1, rows.sub(U1)) } #[inline] - fn spatial_mut(&mut self) - -> MatrixSliceMutMN, C, U1, R> + fn spatial_mut(&mut self) -> MatrixViewMut, C, U1, R> where R: DimNameSub, ShapeConstraint: DimEq, >::Buffer: - StorageMut, + RawStorageMut, { - self.fixed_slice_mut::, C>(1, 0) + let (rows, _cols) = self.shape_generic(); + self.rows_generic_mut(1, rows.sub(U1)) } } #[inline] fn neg(n: &mut N) { - *n = -n.inlined_clone(); + *n = -n.clone(); } /// Spacetime regions regarding an event's light cone. @@ -816,13 +834,11 @@ pub type Frame3 = FrameN; /// $\R^{-,+} = \R^{1,3}$. pub type Frame4 = FrameN; -/// Inertial frame of reference in $n$-dimensional Lorentzian space -/// $\R^{-,+} = \R^{1,n-1}$. +/// Inertial frame of reference in $n$-dimensional Lorentzian space $\R^{-,+} = \R^{1,n-1}$. /// -/// Holds a statically sized direction axis $\hat u \in \R^{n-1}$ and two boost -/// parameters precomputed from either velocity $u^\mu$, rapidity $\vec \zeta$, -/// or velocity ratio $\vec \beta$ whether using [`Self::from_velocity`], -/// [`Self::from_zeta`], or [`Self::from_beta`]: +/// Holds a statically sized direction axis $\hat u \in \R^{n-1}$ and two boost parameters +/// precomputed from either velocity $u^\mu$, rapidity $\vec \zeta$, or velocity ratio $\vec \beta$ +/// whether using [`Self::from_velocity`], [`Self::from_zeta`], or [`Self::from_beta`]: /// /// $$ /// \cosh \zeta = \gamma @@ -842,7 +858,7 @@ where { zeta_cosh: N, zeta_sinh: N, - axis: Unit>>, + axis: Unit>>, } impl FrameN @@ -852,99 +868,127 @@ where DefaultAllocator: Allocator>, { /// Inertial frame of reference with velocity $u^\mu$. - pub fn from_velocity(u: &MatrixMN) -> Self + #[must_use] + pub fn from_velocity(u: &OMatrix) -> Self where - R: Dim, + R: DimNameSub, C: Dim, ShapeConstraint: SameNumberOfRows + SameNumberOfColumns, - DefaultAllocator: Allocator + DefaultAllocator: Allocator, { - let mut scaled_axis = VectorN::zeros(); + let mut scaled_axis = OVector::zeros(); let zeta_cosh = u[0]; - scaled_axis.iter_mut() - .zip(u.fixed_rows::>(1).iter()) + let (rows, _cols) = u.shape_generic(); + scaled_axis + .iter_mut() + .zip(u.rows_generic(1, rows.sub(U1)).iter()) .for_each(|(scaled_axis, &u)| *scaled_axis = u); let (axis, zeta_sinh) = Unit::new_and_get(scaled_axis); - Self { zeta_cosh, zeta_sinh, axis } + Self { + zeta_cosh, + zeta_sinh, + axis, + } } /// Inertial frame of reference with rapidity $\vec \zeta$. + #[must_use] #[inline] - pub fn from_zeta(scaled_axis: VectorN>) -> Self { + pub fn from_zeta(scaled_axis: OVector>) -> Self { let (axis, zeta) = Unit::new_and_get(scaled_axis); Self::from_axis_zeta(axis, zeta) } /// Inertial frame of reference along $\hat u$ with rapidity $\zeta$. + #[must_use] #[inline] - pub fn from_axis_zeta(axis: Unit>>, zeta: N) - -> Self { - Self { zeta_cosh: zeta.cosh(), zeta_sinh: zeta.sinh(), axis } + pub fn from_axis_zeta(axis: Unit>>, zeta: N) -> Self { + Self { + zeta_cosh: zeta.cosh(), + zeta_sinh: zeta.sinh(), + axis, + } } /// Inertial frame of reference with velocity ratio $\vec \beta$. + #[must_use] #[inline] - pub fn from_beta(scaled_axis: VectorN>) -> Self { + pub fn from_beta(scaled_axis: OVector>) -> Self { let (axis, beta) = Unit::new_and_get(scaled_axis); Self::from_axis_beta(axis, beta) } /// Inertial frame of reference along $\hat u$ with velocity ratio $\beta$. + #[must_use] #[inline] - pub fn from_axis_beta(axis: Unit>>, beta: N) - -> Self { - debug_assert!(-N::one() < beta && beta < N::one(), - "Velocity ratio `beta` is out of range (-1, +1)"); + pub fn from_axis_beta(axis: Unit>>, beta: N) -> Self { + debug_assert!( + -N::one() < beta && beta < N::one(), + "Velocity ratio `beta` is out of range (-1, +1)" + ); let gamma = N::one() / (N::one() - beta * beta).sqrt(); - Self { zeta_cosh: gamma, zeta_sinh: beta * gamma, axis } + Self { + zeta_cosh: gamma, + zeta_sinh: beta * gamma, + axis, + } } /// Velocity $u^\mu$. - pub fn velocity(&self) -> VectorN + #[must_use] + pub fn velocity(&self) -> OVector where - DefaultAllocator: Allocator + DefaultAllocator: Allocator, { - let mut u = VectorN::::zeros(); + let mut u = OVector::::zeros(); u[0] = self.gamma(); - u.fixed_rows_mut::>(1).iter_mut() + let (rows, _cols) = u.shape_generic(); + u.rows_generic_mut(1, rows.sub(U1)) + .iter_mut() .zip(self.axis.iter()) .for_each(|(u, &axis)| *u = self.beta_gamma() * axis); u } /// Direction $\hat u$. + #[must_use] #[inline] - pub fn axis(&self) -> Unit>> { + pub fn axis(&self) -> Unit>> { self.axis.clone() } /// Rapidity $\zeta$. + #[must_use] #[inline] pub fn zeta(&self) -> N { self.beta().atanh() } /// Velocity ratio $\beta$. + #[must_use] #[inline] pub fn beta(&self) -> N { self.beta_gamma() / self.gamma() } /// Lorentz factor $\gamma$. + #[must_use] #[inline] - pub fn gamma(&self) -> N { + pub const fn gamma(&self) -> N { self.zeta_cosh } /// Product of velocity ratio $\beta$ and Lorentz factor $\gamma$. + #[must_use] #[inline] - pub fn beta_gamma(&self) -> N { + pub const fn beta_gamma(&self) -> N { self.zeta_sinh } /// Relativistic velocity addition `self`$\oplus$`frame`. /// /// Equals `frame.velocity().boost(&-self.clone()).frame()`. + #[must_use] #[inline] pub fn compose(&self, frame: &Self) -> Self where @@ -954,10 +998,12 @@ where } } -impl FrameN +impl FrameN where + ShapeConstraint: DimEq, N: SimdRealField + Signed + Real, - DefaultAllocator: Allocator, + D: DimNameSub, + DefaultAllocator: Allocator>, { /// $ /// \gdef \Bu {B^{\mu'}\_{\phantom {\mu'} \mu} (\vec \beta_u)} @@ -967,12 +1013,12 @@ where /// \gdef \Ruv {R^{\mu''}\_{\phantom {\mu''} \mu'} (\epsilon)} /// \gdef \Luv {\Lambda^{\mu''}\_{\phantom {\mu''} \mu} (\vec \beta_{\Puv})} /// $ - /// Wigner rotation axis $\widehat {\vec \beta_u \times \vec \beta_v}$ and - /// angle $\epsilon$ of the boost composition `self`$\oplus$`frame`. + /// Wigner rotation axis $\widehat {\vec \beta_u \times \vec \beta_v}$ and angle $\epsilon$ of + /// the boost composition `self`$\oplus$`frame`. /// - /// The composition of two pure boosts, $\Bu$ to `self` followed by $\Bv$ - /// to `frame`, results in a composition of a pure boost $\Buv$ and a - /// *non-vanishing* spatial rotation $\Ruv$ for *non-collinear* boosts: + /// The composition of two pure boosts, $\Bu$ to `self` followed by $\Bv$ to `frame`, results in + /// a composition of a pure boost $\Buv$ and a *non-vanishing* spatial rotation $\Ruv$ for + /// *non-collinear* boosts: /// /// $$ /// \Luv = \Ruv \Buv = \Bv \Bu @@ -991,9 +1037,9 @@ where /// $$ /// /// ``` - /// use nalgebra::Vector3; - /// use nalgebra_spacetime::{LorentzianN, Frame4}; /// use approx::{assert_abs_diff_ne, assert_ulps_eq}; + /// use nalgebra::Vector3; + /// use nalgebra_spacetime::{Frame4, LorentzianN}; /// /// let u = Frame4::from_beta(Vector3::new(0.18, 0.73, 0.07)); /// let v = Frame4::from_beta(Vector3::new(0.41, 0.14, 0.25)); @@ -1008,7 +1054,8 @@ where /// assert_ulps_eq!(angle, ucv.angle(&vcu), epsilon = 1e-15); /// assert_ulps_eq!(axis, ucv.cross(&vcu).normalize(), epsilon = 1e-15); /// ``` - pub fn axis_angle(&self, frame: &Self) -> (Unit>, N) { + #[must_use] + pub fn axis_angle(&self, frame: &Self) -> (Unit>>, N) { let (u, v) = (self, frame); let (axis, sin) = Unit::new_and_get(u.axis().cross(&v.axis())); let uv = u.axis().dot(&v.axis()); @@ -1021,15 +1068,15 @@ where (axis, (sum / prod * bg * sin).asin()) } - /// Wigner rotation matrix $R(\widehat {\vec \beta_u \times \vec \beta_v}, - /// \epsilon)$ of the boost composition `self`$\oplus$`frame`. + /// Wigner rotation matrix $R(\widehat {\vec \beta_u \times \vec \beta_v}, \epsilon)$ of the + /// boost composition `self`$\oplus$`frame`. /// /// See [`Self::axis_angle`] for further details. /// /// ``` - /// use nalgebra::{Vector3, Matrix4}; - /// use nalgebra_spacetime::{LorentzianN, Frame4}; /// use approx::{assert_ulps_eq, assert_ulps_ne}; + /// use nalgebra::{Matrix4, Vector3}; + /// use nalgebra_spacetime::{Frame4, LorentzianN}; /// /// let u = Frame4::from_beta(Vector3::new(0.18, 0.73, 0.07)); /// let v = Frame4::from_beta(Vector3::new(0.41, 0.14, 0.25)); @@ -1048,20 +1095,25 @@ where /// assert_ulps_eq!(rotation_ucv * boost_ucv, boost_v * boost_u); /// assert_ulps_eq!(boost_vcu * rotation_ucv, boost_v * boost_u); /// ``` + #[must_use] pub fn rotation(&self, frame: &Self) -> Matrix4 where N::Element: SimdRealField, - DefaultAllocator: Allocator, + DefaultAllocator: Allocator, { let mut m = Matrix4::::identity(); let (axis, angle) = self.axis_angle(frame); - let r = Rotation3::::from_axis_angle(&axis, angle); - m.fixed_slice_mut::(1, 1).copy_from(r.matrix()); + let axis = axis.into_inner(); + let axis = Unit::new_unchecked(Vector3::new(axis[0], axis[1], axis[2])); + let r = Rotation3::from_axis_angle(&axis, angle); + let (rows, cols) = m.shape_generic(); + m.generic_view_mut((1, 1), (rows.sub(U1), cols.sub(U1))) + .copy_from(r.matrix()); m } } -impl From> for FrameN +impl From> for FrameN where N: SimdRealField + Signed + Real, R: DimNameSub, @@ -1070,12 +1122,12 @@ where DefaultAllocator: Allocator + Allocator>, { #[inline] - fn from(u: MatrixMN) -> Self { + fn from(u: OMatrix) -> Self { u.frame() } } -impl From> for VectorN +impl From> for OVector where N: SimdRealField + Signed + Real, D: DimNameSub, @@ -1127,15 +1179,15 @@ where /// Momentum in $n$-dimensional Lorentzian space $\R^{-,+} = \R^{1,n-1}$. /// -/// Assuming unit system with speed of light $c=1$ and rest mass $m$ as -/// timelike norm in spacelike sign convention as in: +/// Assuming unit system with speed of light $c=1$ and rest mass $m$ as timelike norm in spacelike +/// sign convention as in: /// /// $$ /// m^2=E^2-\vec {p}^2=-p_\mu p^\mu /// $$ /// -/// Where $p^\mu$ is the $n$-momentum with energy $E$ as temporal $p^0$ and -/// momentum $\vec p$ as spatial $p^i$ components: +/// Where $p^\mu$ is the $n$-momentum with energy $E$ as temporal $p^0$ and momentum $\vec p$ as +/// spatial $p^i$ components: /// /// $$ /// p^\mu = m u^\mu = m \begin{pmatrix} @@ -1145,8 +1197,7 @@ where /// \end{pmatrix} /// $$ /// -/// With $n$-velocity $u^\mu$, Lorentz factor $\gamma$, and velocity ratio -/// $\vec \beta$. +/// With $n$-velocity $u^\mu$, Lorentz factor $\gamma$, and velocity ratio $\vec \beta$. #[derive(Debug, PartialEq, Clone)] pub struct MomentumN where @@ -1154,7 +1205,7 @@ where D: DimNameSub, DefaultAllocator: Allocator, { - momentum: VectorN, + momentum: OVector, } impl MomentumN @@ -1165,31 +1216,37 @@ where { /// Momentum with spacetime [`LorentzianN::split`], `energy` $E$ and /// `momentum` $\vec p$. + #[must_use] #[inline] - pub fn from_split(energy: &N, momentum: &VectorN>) - -> Self + pub fn from_split(energy: &N, momentum: &OVector>) -> Self where DefaultAllocator: Allocator>, >::Buffer: StorageMut, { - Self { momentum: VectorN::::from_split(energy, momentum) } + Self { + momentum: OVector::::from_split(energy, momentum), + } } /// Momentum $p^\mu=m u^\mu$ with rest `mass` $m$ at `velocity` $u^\mu$. + #[must_use] #[inline] - pub fn from_mass_at_velocity(mass: N, velocity: VectorN) -> Self + pub fn from_mass_at_velocity(mass: N, velocity: OVector) -> Self where DefaultAllocator: Allocator>, { - Self { momentum: velocity * mass } + Self { + momentum: velocity * mass, + } } /// Momentum $p^\mu$ with rest `mass` $m$ in `frame`. /// /// Equals `frame.velocity() * mass`. + #[must_use] #[inline] - pub fn from_mass_in_frame(mass: N, frame: FrameN) -> Self + pub fn from_mass_in_frame(mass: N, frame: &FrameN) -> Self where DefaultAllocator: Allocator>, { @@ -1197,34 +1254,39 @@ where } /// Momentum $p^\mu$ with rest `mass` $m$ in center-of-momentum frame. + #[must_use] #[inline] pub fn from_mass_at_rest(mass: N) -> Self { - let mut momentum = VectorN::::zeros(); + let mut momentum = OVector::::zeros(); *momentum.temporal_mut() = mass; Self { momentum } } - /// Rest mass $m$ as timelike norm $\sqrt{-p_\mu p^\mu}$ in spacelike sign - /// convention. + /// Rest mass $m$ as timelike norm $\sqrt{-p_\mu p^\mu}$ in spacelike sign convention. + #[must_use] #[inline] pub fn mass(&self) -> N { self.momentum.timelike_norm() } /// Velocity $u^\mu$ as momentum $p^\mu$ divided by rest `mass()` $m$. - pub fn velocity(&self) -> VectorN { + #[must_use] + #[inline] + pub fn velocity(&self) -> OVector { self.momentum.clone() / self.mass() } /// Energy $E$ as [`LorentzianN::temporal`] component. + #[must_use] #[inline] pub fn energy(&self) -> &N { self.momentum.temporal() } /// Momentum $\vec p$ as [`LorentzianN::spatial`] components. + #[must_use] #[inline] - pub fn momentum(&self) -> VectorSliceN, U1, D> + pub fn momentum(&self) -> VectorView, U1, D> where DefaultAllocator: Allocator, >::Buffer: @@ -1234,19 +1296,19 @@ where } } -impl From> for MomentumN +impl From> for MomentumN where N: SimdRealField + Signed + Real, D: DimNameSub, DefaultAllocator: Allocator, { #[inline] - fn from(momentum: VectorN) -> Self { + fn from(momentum: OVector) -> Self { Self { momentum } } } -impl From> for VectorN +impl From> for OVector where N: SimdRealField + Signed + Real, D: DimNameSub, @@ -1268,7 +1330,9 @@ where #[inline] fn add(self, rhs: Self) -> Self::Output { - Self { momentum: self.momentum + rhs.momentum } + Self { + momentum: self.momentum + rhs.momentum, + } } } @@ -1282,7 +1346,9 @@ where #[inline] fn sub(self, rhs: Self) -> Self::Output { - Self { momentum: self.momentum - rhs.momentum } + Self { + momentum: self.momentum - rhs.momentum, + } } }