/rust/registry/src/index.crates.io-1949cf8c6b5b557f/nalgebra-0.34.1/src/lib.rs
Line | Count | Source |
1 | | /*! |
2 | | # nalgebra |
3 | | |
4 | | **nalgebra** is a linear algebra library written for Rust targeting: |
5 | | |
6 | | * General-purpose linear algebra (still lacks a lot of features…) |
7 | | * Real-time computer graphics. |
8 | | * Real-time computer physics. |
9 | | |
10 | | ## Using **nalgebra** |
11 | | You will need the last stable build of the [rust compiler](https://www.rust-lang.org) |
12 | | and the official package manager: [cargo](https://github.com/rust-lang/cargo). |
13 | | |
14 | | Simply add the following to your `Cargo.toml` file: |
15 | | |
16 | | ```ignore |
17 | | [dependencies] |
18 | | // TODO: replace the * by the latest version. |
19 | | nalgebra = "*" |
20 | | ``` |
21 | | |
22 | | |
23 | | Most useful functionalities of **nalgebra** are grouped in the root module `nalgebra::`. |
24 | | |
25 | | However, the recommended way to use **nalgebra** is to import types and traits |
26 | | explicitly, and call free-functions using the `na::` prefix: |
27 | | |
28 | | ``` |
29 | | #[macro_use] |
30 | | extern crate approx; // For the macro assert_relative_eq! |
31 | | extern crate nalgebra as na; |
32 | | use na::{Vector3, Rotation3}; |
33 | | |
34 | | fn main() { |
35 | | let axis = Vector3::x_axis(); |
36 | | let angle = 1.57; |
37 | | let b = Rotation3::from_axis_angle(&axis, angle); |
38 | | |
39 | | assert_relative_eq!(b.axis().unwrap(), axis); |
40 | | assert_relative_eq!(b.angle(), angle); |
41 | | } |
42 | | ``` |
43 | | |
44 | | |
45 | | ## Features |
46 | | **nalgebra** is meant to be a general-purpose, low-dimensional, linear algebra library, with |
47 | | an optimized set of tools for computer graphics and physics. Those features include: |
48 | | |
49 | | * A single parametrizable type [`Matrix`] for vectors, (square or rectangular) matrices, and |
50 | | slices with dimensions known either at compile-time (using type-level integers) or at runtime. |
51 | | * Matrices and vectors with compile-time sizes are statically allocated while dynamic ones are |
52 | | allocated on the heap. |
53 | | * Convenient aliases for low-dimensional matrices and vectors: [`Vector1`] to |
54 | | [`Vector6`] and [`Matrix1x1`](Matrix1) to [`Matrix6x6`](Matrix6), including rectangular |
55 | | matrices like [`Matrix2x5`]. |
56 | | * Points sizes known at compile time, and convenience aliases: [`Point1`] to |
57 | | [`Point6`]. |
58 | | * Translation (seen as a transformation that composes by multiplication): |
59 | | [`Translation2`], [`Translation3`]. |
60 | | * Rotation matrices: [`Rotation2`], [`Rotation3`]. |
61 | | * Quaternions: [`Quaternion`], [`UnitQuaternion`] (for 3D rotation). |
62 | | * Unit complex numbers can be used for 2D rotation: [`UnitComplex`]. |
63 | | * Algebraic entities with a norm equal to one: [`Unit<T>`](Unit), e.g., `Unit<Vector3<f32>>`. |
64 | | * Isometries (translation ⨯ rotation): [`Isometry2`], [`Isometry3`] |
65 | | * Similarity transformations (translation ⨯ rotation ⨯ uniform scale): |
66 | | [`Similarity2`], [`Similarity3`]. |
67 | | * Affine transformations stored as a homogeneous matrix: |
68 | | [`Affine2`], [`Affine3`]. |
69 | | * Projective (i.e. invertible) transformations stored as a homogeneous matrix: |
70 | | [`Projective2`], [`Projective3`]. |
71 | | * General transformations that does not have to be invertible, stored as a homogeneous matrix: |
72 | | [`Transform2`], [`Transform3`]. |
73 | | * 3D projections for computer graphics: [`Perspective3`], |
74 | | [`Orthographic3`]. |
75 | | * Matrix factorizations: [`Cholesky`], [`QR`], [`LU`], [`FullPivLU`], |
76 | | [`SVD`], [`Schur`], [`Hessenberg`], [`SymmetricEigen`]. |
77 | | * Insertion and removal of rows of columns of a matrix. |
78 | | */ |
79 | | |
80 | | #![deny( |
81 | | missing_docs, |
82 | | nonstandard_style, |
83 | | unused_variables, |
84 | | unused_mut, |
85 | | unused_parens, |
86 | | rust_2018_idioms, |
87 | | rust_2024_compatibility, |
88 | | future_incompatible, |
89 | | missing_copy_implementations |
90 | | )] |
91 | | #![cfg_attr(not(feature = "rkyv-serialize-no-std"), deny(unused_results))] // TODO: deny this globally once bytecheck stops generating unused results. |
92 | | #![doc( |
93 | | html_favicon_url = "https://nalgebra.rs/img/favicon.ico", |
94 | | html_root_url = "https://docs.rs/nalgebra/0.25.0" |
95 | | )] |
96 | | #![cfg_attr(not(feature = "std"), no_std)] |
97 | | // only enables the `doc_cfg` feature when |
98 | | // the `docsrs` configuration attribute is defined |
99 | | #![cfg_attr(docsrs, feature(doc_cfg))] |
100 | | |
101 | | /// Generates an appropriate deprecation note with a suggestion for replacement. |
102 | | /// |
103 | | /// Used for deprecating slice types in various locations throughout the library. |
104 | | /// See #1076 for more information. |
105 | | macro_rules! slice_deprecation_note { |
106 | | ($replacement:ident) => { |
107 | | concat!("Use ", stringify!($replacement), |
108 | | r###" instead. See [issue #1076](https://github.com/dimforge/nalgebra/issues/1076) for more information."###) |
109 | | } |
110 | | } |
111 | | |
112 | | pub(crate) use slice_deprecation_note; |
113 | | |
114 | | #[cfg(feature = "rand-no-std")] |
115 | | extern crate rand_package as rand; |
116 | | |
117 | | #[cfg(feature = "serde-serialize-no-std")] |
118 | | #[macro_use] |
119 | | extern crate serde; |
120 | | |
121 | | #[macro_use] |
122 | | extern crate approx; |
123 | | extern crate num_traits as num; |
124 | | |
125 | | #[cfg(all(feature = "alloc", not(feature = "std")))] |
126 | | #[cfg_attr(test, macro_use)] |
127 | | extern crate alloc; |
128 | | |
129 | | #[cfg(not(feature = "std"))] |
130 | | extern crate core as std; |
131 | | |
132 | | #[macro_use] |
133 | | #[cfg(feature = "io")] |
134 | | extern crate pest_derive; |
135 | | |
136 | | pub mod base; |
137 | | #[cfg(feature = "debug")] |
138 | | pub mod debug; |
139 | | pub mod geometry; |
140 | | #[cfg(feature = "io")] |
141 | | pub mod io; |
142 | | pub mod linalg; |
143 | | #[cfg(feature = "proptest-support")] |
144 | | pub mod proptest; |
145 | | #[cfg(feature = "sparse")] |
146 | | pub mod sparse; |
147 | | mod third_party; |
148 | | |
149 | | pub use crate::base::*; |
150 | | pub use crate::geometry::*; |
151 | | pub use crate::linalg::*; |
152 | | #[cfg(feature = "sparse")] |
153 | | pub use crate::sparse::*; |
154 | | #[cfg(feature = "std")] |
155 | | #[deprecated( |
156 | | note = "The 'core' module is being renamed to 'base' to avoid conflicts with the 'core' crate." |
157 | | )] |
158 | | pub use base as core; |
159 | | |
160 | | #[cfg(feature = "macros")] |
161 | | pub use nalgebra_macros::{dmatrix, dvector, matrix, point, stack, vector}; |
162 | | |
163 | | use simba::scalar::SupersetOf; |
164 | | use std::cmp::{self, Ordering, PartialOrd}; |
165 | | |
166 | | use num::{One, Signed, Zero}; |
167 | | |
168 | | use base::allocator::Allocator; |
169 | | pub use num_complex::Complex; |
170 | | pub use simba::scalar::{ |
171 | | ClosedAddAssign, ClosedDivAssign, ClosedMulAssign, ClosedSubAssign, ComplexField, Field, |
172 | | RealField, |
173 | | }; |
174 | | pub use simba::simd::{SimdBool, SimdComplexField, SimdPartialOrd, SimdRealField, SimdValue}; |
175 | | |
176 | | /// Gets the multiplicative identity element. |
177 | | /// |
178 | | /// # See also: |
179 | | /// |
180 | | /// * [`origin()`](crate::OPoint::origin) |
181 | | /// * [`zero()`] |
182 | | #[inline] |
183 | | pub fn one<T: One>() -> T { |
184 | | T::one() |
185 | | } |
186 | | |
187 | | /// Gets the additive identity element. |
188 | | /// |
189 | | /// # See also: |
190 | | /// |
191 | | /// * [`one()`] |
192 | | /// * [`origin()`](crate::OPoint::origin) |
193 | | #[inline] |
194 | | pub fn zero<T: Zero>() -> T { |
195 | | T::zero() |
196 | | } |
197 | | |
198 | | /* |
199 | | * |
200 | | * Ordering |
201 | | * |
202 | | */ |
203 | | // XXX: this is very naive and could probably be optimized for specific types. |
204 | | // XXX: also, we might just want to use divisions, but assuming `val` is usually not far from `min` |
205 | | // or `max`, would it still be more efficient? |
206 | | /// Wraps `val` into the range `[min, max]` using modular arithmetics. |
207 | | /// |
208 | | /// The range must not be empty. |
209 | | #[must_use] |
210 | | #[inline] |
211 | | pub fn wrap<T>(mut val: T, min: T, max: T) -> T |
212 | | where |
213 | | T: Copy + PartialOrd + ClosedAddAssign + ClosedSubAssign, |
214 | | { |
215 | | assert!(min < max, "Invalid wrapping bounds."); |
216 | | let width = max - min; |
217 | | |
218 | | if val < min { |
219 | | val += width; |
220 | | |
221 | | while val < min { |
222 | | val += width |
223 | | } |
224 | | } else if val > max { |
225 | | val -= width; |
226 | | |
227 | | while val > max { |
228 | | val -= width |
229 | | } |
230 | | } |
231 | | |
232 | | val |
233 | | } |
234 | | |
235 | | /// Returns a reference to the input value clamped to the interval `[min, max]`. |
236 | | /// |
237 | | /// In particular: |
238 | | /// * If `min < val < max`, this returns `val`. |
239 | | /// * If `val <= min`, this returns `min`. |
240 | | /// * If `val >= max`, this returns `max`. |
241 | | #[must_use] |
242 | | #[inline] |
243 | | pub fn clamp<T: PartialOrd>(val: T, min: T, max: T) -> T { |
244 | | if val > min { |
245 | | if val < max { val } else { max } |
246 | | } else { |
247 | | min |
248 | | } |
249 | | } |
250 | | |
251 | | /// Same as `cmp::max`. |
252 | | #[inline] |
253 | 0 | pub fn max<T: Ord>(a: T, b: T) -> T { |
254 | 0 | cmp::max(a, b) |
255 | 0 | } |
256 | | |
257 | | /// Same as `cmp::min`. |
258 | | #[inline] |
259 | 4.75k | pub fn min<T: Ord>(a: T, b: T) -> T { |
260 | 4.75k | cmp::min(a, b) |
261 | 4.75k | } |
262 | | |
263 | | /// The absolute value of `a`. |
264 | | /// |
265 | | /// Deprecated: Use [`Matrix::abs()`] or [`ComplexField::abs()`] instead. |
266 | | #[deprecated(note = "use the inherent method `Matrix::abs` or `ComplexField::abs` instead")] |
267 | | #[inline] |
268 | | pub fn abs<T: Signed>(a: &T) -> T { |
269 | | a.abs() |
270 | | } |
271 | | |
272 | | /// Returns the infimum of `a` and `b`. |
273 | | #[deprecated(note = "use the inherent method `Matrix::inf` instead")] |
274 | | #[inline] |
275 | | pub fn inf<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C> |
276 | | where |
277 | | T: Scalar + SimdPartialOrd, |
278 | | DefaultAllocator: Allocator<R, C>, |
279 | | { |
280 | | a.inf(b) |
281 | | } |
282 | | |
283 | | /// Returns the supremum of `a` and `b`. |
284 | | #[deprecated(note = "use the inherent method `Matrix::sup` instead")] |
285 | | #[inline] |
286 | | pub fn sup<T, R: Dim, C: Dim>(a: &OMatrix<T, R, C>, b: &OMatrix<T, R, C>) -> OMatrix<T, R, C> |
287 | | where |
288 | | T: Scalar + SimdPartialOrd, |
289 | | DefaultAllocator: Allocator<R, C>, |
290 | | { |
291 | | a.sup(b) |
292 | | } |
293 | | |
294 | | /// Returns simultaneously the infimum and supremum of `a` and `b`. |
295 | | #[deprecated(note = "use the inherent method `Matrix::inf_sup` instead")] |
296 | | #[inline] |
297 | | pub fn inf_sup<T, R: Dim, C: Dim>( |
298 | | a: &OMatrix<T, R, C>, |
299 | | b: &OMatrix<T, R, C>, |
300 | | ) -> (OMatrix<T, R, C>, OMatrix<T, R, C>) |
301 | | where |
302 | | T: Scalar + SimdPartialOrd, |
303 | | DefaultAllocator: Allocator<R, C>, |
304 | | { |
305 | | a.inf_sup(b) |
306 | | } |
307 | | |
308 | | /// Compare `a` and `b` using a partial ordering relation. |
309 | | #[inline] |
310 | | pub fn partial_cmp<T: PartialOrd>(a: &T, b: &T) -> Option<Ordering> { |
311 | | a.partial_cmp(b) |
312 | | } |
313 | | |
314 | | /// Returns `true` iff `a` and `b` are comparable and `a < b`. |
315 | | #[inline] |
316 | | pub fn partial_lt<T: PartialOrd>(a: &T, b: &T) -> bool { |
317 | | a.lt(b) |
318 | | } |
319 | | |
320 | | /// Returns `true` iff `a` and `b` are comparable and `a <= b`. |
321 | | #[inline] |
322 | | pub fn partial_le<T: PartialOrd>(a: &T, b: &T) -> bool { |
323 | | a.le(b) |
324 | | } |
325 | | |
326 | | /// Returns `true` iff `a` and `b` are comparable and `a > b`. |
327 | | #[inline] |
328 | | pub fn partial_gt<T: PartialOrd>(a: &T, b: &T) -> bool { |
329 | | a.gt(b) |
330 | | } |
331 | | |
332 | | /// Returns `true` iff `a` and `b` are comparable and `a >= b`. |
333 | | #[inline] |
334 | | pub fn partial_ge<T: PartialOrd>(a: &T, b: &T) -> bool { |
335 | | a.ge(b) |
336 | | } |
337 | | |
338 | | /// Return the minimum of `a` and `b` if they are comparable. |
339 | | #[inline] |
340 | | pub fn partial_min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> { |
341 | | if let Some(ord) = a.partial_cmp(b) { |
342 | | match ord { |
343 | | Ordering::Greater => Some(b), |
344 | | _ => Some(a), |
345 | | } |
346 | | } else { |
347 | | None |
348 | | } |
349 | | } |
350 | | |
351 | | /// Return the maximum of `a` and `b` if they are comparable. |
352 | | #[inline] |
353 | | pub fn partial_max<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<&'a T> { |
354 | | if let Some(ord) = a.partial_cmp(b) { |
355 | | match ord { |
356 | | Ordering::Less => Some(b), |
357 | | _ => Some(a), |
358 | | } |
359 | | } else { |
360 | | None |
361 | | } |
362 | | } |
363 | | |
364 | | /// Clamp `value` between `min` and `max`. Returns `None` if `value` is not comparable to |
365 | | /// `min` or `max`. |
366 | | #[inline] |
367 | | pub fn partial_clamp<'a, T: PartialOrd>(value: &'a T, min: &'a T, max: &'a T) -> Option<&'a T> { |
368 | | if let (Some(cmp_min), Some(cmp_max)) = (value.partial_cmp(min), value.partial_cmp(max)) { |
369 | | if cmp_min == Ordering::Less { |
370 | | Some(min) |
371 | | } else if cmp_max == Ordering::Greater { |
372 | | Some(max) |
373 | | } else { |
374 | | Some(value) |
375 | | } |
376 | | } else { |
377 | | None |
378 | | } |
379 | | } |
380 | | |
381 | | /// Sorts two values in increasing order using a partial ordering. |
382 | | #[inline] |
383 | | pub fn partial_sort2<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> Option<(&'a T, &'a T)> { |
384 | | if let Some(ord) = a.partial_cmp(b) { |
385 | | match ord { |
386 | | Ordering::Less => Some((a, b)), |
387 | | _ => Some((b, a)), |
388 | | } |
389 | | } else { |
390 | | None |
391 | | } |
392 | | } |
393 | | |
394 | | /* |
395 | | * |
396 | | * Point operations. |
397 | | * |
398 | | */ |
399 | | /// The center of two points. |
400 | | /// |
401 | | /// # See also: |
402 | | /// |
403 | | /// * [`distance()`] |
404 | | /// * [`distance_squared()`] |
405 | | #[inline] |
406 | | pub fn center<T: SimdComplexField, const D: usize>( |
407 | | p1: &Point<T, D>, |
408 | | p2: &Point<T, D>, |
409 | | ) -> Point<T, D> { |
410 | | ((&p1.coords + &p2.coords) * convert::<_, T>(0.5)).into() |
411 | | } |
412 | | |
413 | | /// The distance between two points. |
414 | | /// |
415 | | /// # See also: |
416 | | /// |
417 | | /// * [`center()`] |
418 | | /// * [`distance_squared()`] |
419 | | #[inline] |
420 | | pub fn distance<T: SimdComplexField, const D: usize>( |
421 | | p1: &Point<T, D>, |
422 | | p2: &Point<T, D>, |
423 | | ) -> T::SimdRealField { |
424 | | (&p2.coords - &p1.coords).norm() |
425 | | } |
426 | | |
427 | | /// The squared distance between two points. |
428 | | /// |
429 | | /// # See also: |
430 | | /// |
431 | | /// * [`center()`] |
432 | | /// * [`distance()`] |
433 | | #[inline] |
434 | | pub fn distance_squared<T: SimdComplexField, const D: usize>( |
435 | | p1: &Point<T, D>, |
436 | | p2: &Point<T, D>, |
437 | | ) -> T::SimdRealField { |
438 | | (&p2.coords - &p1.coords).norm_squared() |
439 | | } |
440 | | |
441 | | /* |
442 | | * Cast |
443 | | */ |
444 | | /// Converts an object from one type to an equivalent or more general one. |
445 | | /// |
446 | | /// See also [`try_convert()`] for conversion to more specific types. |
447 | | /// |
448 | | /// # See also: |
449 | | /// |
450 | | /// * [`convert_ref()`] |
451 | | /// * [`convert_ref_unchecked()`] |
452 | | /// * [`is_convertible()`] |
453 | | /// * [`try_convert()`] |
454 | | /// * [`try_convert_ref()`] |
455 | | #[inline] |
456 | 0 | pub fn convert<From, To: SupersetOf<From>>(t: From) -> To { |
457 | 0 | To::from_subset(&t) |
458 | 0 | } |
459 | | |
460 | | /// Attempts to convert an object to a more specific one. |
461 | | /// |
462 | | /// See also [`convert()`] for conversion to more general types. |
463 | | /// |
464 | | /// # See also: |
465 | | /// |
466 | | /// * [`convert()`] |
467 | | /// * [`convert_ref()`] |
468 | | /// * [`convert_ref_unchecked()`] |
469 | | /// * [`is_convertible()`] |
470 | | /// * [`try_convert_ref()`] |
471 | | #[inline] |
472 | | pub fn try_convert<From: SupersetOf<To>, To>(t: From) -> Option<To> { |
473 | | t.to_subset() |
474 | | } |
475 | | |
476 | | /// Indicates if [`try_convert()`] will succeed without |
477 | | /// actually performing the conversion. |
478 | | /// |
479 | | /// # See also: |
480 | | /// |
481 | | /// * [`convert()`] |
482 | | /// * [`convert_ref()`] |
483 | | /// * [`convert_ref_unchecked()`] |
484 | | /// * [`try_convert()`] |
485 | | /// * [`try_convert_ref()`] |
486 | | #[inline] |
487 | | pub fn is_convertible<From: SupersetOf<To>, To>(t: &From) -> bool { |
488 | | t.is_in_subset() |
489 | | } |
490 | | |
491 | | /// Use with care! Same as [`try_convert()`] but |
492 | | /// without any property checks. |
493 | | /// |
494 | | /// # See also: |
495 | | /// |
496 | | /// * [`convert()`] |
497 | | /// * [`convert_ref()`] |
498 | | /// * [`convert_ref_unchecked()`] |
499 | | /// * [`is_convertible()`] |
500 | | /// * [`try_convert()`] |
501 | | /// * [`try_convert_ref()`] |
502 | | #[inline] |
503 | | pub fn convert_unchecked<From: SupersetOf<To>, To>(t: From) -> To { |
504 | | t.to_subset_unchecked() |
505 | | } |
506 | | |
507 | | /// Converts an object from one type to an equivalent or more general one. |
508 | | /// |
509 | | /// # See also: |
510 | | /// |
511 | | /// * [`convert()`] |
512 | | /// * [`convert_ref_unchecked()`] |
513 | | /// * [`is_convertible()`] |
514 | | /// * [`try_convert()`] |
515 | | /// * [`try_convert_ref()`] |
516 | | #[inline] |
517 | | pub fn convert_ref<From, To: SupersetOf<From>>(t: &From) -> To { |
518 | | To::from_subset(t) |
519 | | } |
520 | | |
521 | | /// Attempts to convert an object to a more specific one. |
522 | | /// |
523 | | /// # See also: |
524 | | /// |
525 | | /// * [`convert()`] |
526 | | /// * [`convert_ref()`] |
527 | | /// * [`convert_ref_unchecked()`] |
528 | | /// * [`is_convertible()`] |
529 | | /// * [`try_convert()`] |
530 | | #[inline] |
531 | | pub fn try_convert_ref<From: SupersetOf<To>, To>(t: &From) -> Option<To> { |
532 | | t.to_subset() |
533 | | } |
534 | | |
535 | | /// Use with care! Same as [`try_convert()`] but |
536 | | /// without any property checks. |
537 | | /// |
538 | | /// # See also: |
539 | | /// |
540 | | /// * [`convert()`] |
541 | | /// * [`convert_ref()`] |
542 | | /// * [`is_convertible()`] |
543 | | /// * [`try_convert()`] |
544 | | /// * [`try_convert_ref()`] |
545 | | #[inline] |
546 | | pub fn convert_ref_unchecked<From: SupersetOf<To>, To>(t: &From) -> To { |
547 | | t.to_subset_unchecked() |
548 | | } |