vectora/lib.rs
1//! A vector computation library
2//!
3//! # Contents
4//!
5//! - [About](#about)
6//! - [Safety Guarantee](#safety-guarantee)
7//! - [Versioning](#versioning)
8//! - [Minimum Rust Version Compatibility Policy](#minimum-rust-version-compatibility-policy)
9//! - [Source](#source)
10//! - [Changes](#changes)
11//! - [Issues](#issues)
12//! - [Contributing](#contributing)
13//! - [License](#license)
14//! - [Getting Started](#getting-started)
15//! - [Add Vectora to Your Project](#add-vectora-to-your-project)
16//! - [Optional Crate Features](#optional-crate-features)
17//! - [Numeric Type Support](#numeric-type-support)
18//! - [Initialization](#initialization)
19//! - [Numeric Type Casts](#numeric-type-casts)
20//! - [Access and Assignment with Indexing](#access-and-assignment-with-indexing)
21//! - [Slicing](#slicing)
22//! - [Partial Equivalence Testing](#partial-equivalence-testing)
23//! - [Iteration and Loops](#iteration-and-loops)
24//! - [Vector Arithmetic](#vector-arithmetic)
25//! - [Methods for Vector Operations](#methods-for-vector-operations)
26//! - [Descriptive Statistics](#descriptive-statistics)
27//! - [Working with Rust Standard Library Types](#working-with-rust-standard-library-types)
28//!
29//!
30//! # About
31//!
32//! Vectora is a library for n-dimensional vector computation with real and complex scalar types.
33//! The main library entry point is the [`Vector`] struct. Please see the [Gettting Started guide](#getting-started)
34//! for a detailed library overview with examples.
35//!
36//! # Safety Guarantee
37//!
38//! The current default distribution does not contain `unsafe` code blocks.
39//!
40//! # Versioning
41//!
42//! This project uses [semantic versioning](https://semver.org/) and is currently in a pre-v1.0 stage
43//! of development. The public API should not be considered stable across release versions at this
44//! time.
45//!
46//! # Minimum Rust Version Compatibility Policy
47//!
48//! This project parameterizes generics by constants and relies on the [constant generics feature support
49//! that was stabilized in Rust v1.51](https://github.com/rust-lang/rust/pull/79135). The minimum
50//! supported `rustc` version is believed to be v1.51.0.
51//!
52//! # Source
53//!
54//! The source files are available at <https://github.com/chrissimpkins/vectora>.
55//!
56//! # Changes
57//!
58//! Please see the [CHANGELOG.md](https://github.com/chrissimpkins/vectora/blob/main/CHANGELOG.md) document in the source repository.
59//!
60//! # Issues
61//!
62//! The [issue tracker](https://github.com/chrissimpkins/vectora/issues) is available on the GitHub repository.
63//! Don't be shy. Please report any issues that you identify so that we can address them.
64//!
65//! # Contributing
66//!
67//! Contributions are welcomed. Developer documentation is available in the source
68//! repository [README](https://github.com/chrissimpkins/vectora).
69//!
70//! Submit your source or documentation changes as a GitHub pull request on
71//! the [source repository](https://github.com/chrissimpkins/vectora).
72//!
73//! # License
74//!
75//! Vectora is released under the [Apache License v2.0](https://github.com/chrissimpkins/vectora/blob/main/LICENSE.md).
76//! Please review the full text of the license for details.
77//!
78//! # Getting Started
79//!
80//! See the [`Vector`] page for detailed API documentation of the main library
81//! entry point.
82//!
83//! The following section provides an overview of common tasks and will get you up
84//! and running with the library quickly.
85//!
86//! ## Add Vectora to Your Project
87//!
88//! Import the vectora library in the `[dependencies]` section
89//! of your `Cargo.toml` file:
90//!
91//! ```toml
92//! [dependencies]
93//! vectora = "0.8.1"
94//! ```
95//!
96//! The examples below assume the following [`Vector`] struct import in
97//! your Rust source files:
98//!
99//! ```
100//! use vectora::Vector;
101//! ```
102//!
103//! ## Optional Crate Features
104//!
105//! Optional features are defined in your `Cargo.toml` configuration file:
106//!
107//! ```yaml
108//! [dependencies]
109//! vectora = { version = "VERSION_NUMBER", features = ["parallel"] }
110//! ```
111//!
112//! Replace `VERSION_NUMBER` in the example above with the vectora crate version number.
113//!
114//! Conditional compilation and optional dependency installation are available for the following features:
115//!
116//! - **`parallel`**: Installs an optional [rayon crate](https://docs.rs/crate/rayon/latest) dependency and broadens the [`Vector`] API with
117//! parallel iterator and parallel slice support. This feature includes implementations of `Vector::into_par_iter`, `Vector::par_iter`,
118//! `Vector::par_iter_mut`, `Vector::as_parallel_slice`, and `Vector::as_parallel_slice_mut` methods with support for the rayon trait-defined
119//! [parallel iterator](https://docs.rs/rayon/latest/rayon/iter/trait.ParallelIterator.html#provided-methods),
120//! [immutable parallel slice](https://docs.rs/rayon/latest/rayon/slice/trait.ParallelSlice.html), and
121//! [mutable parallel slice](https://docs.rs/rayon/latest/rayon/slice/trait.ParallelSliceMut.html) APIs.
122//!
123//!
124//! ## Numeric Type Support
125//!
126//! This library supports computation with real and complex scalar number types.
127//!
128//! ### Integers
129//!
130//! Support is available for the following primitive integer data types:
131//!
132//! - [`i8`]
133//! - [`i16`]
134//! - [`i32`]
135//! - [`i64`]
136//! - [`i128`]
137//! - [`u8`]
138//! - [`u16`]
139//! - [`u32`]
140//! - [`u64`]
141//! - [`u128`]
142//! - [`usize`]
143//! - [`isize`]
144//!
145//! **Note**: overflowing integer arithmetic uses the default
146//! Rust standard library approach of panics in debug builds
147//! and twos complement wrapping in release builds. You will not encounter
148//! undefined behavior with either build type, but this approach
149//! may not be what you want. Please consider this issue and understand
150//! the library source implementations if your use case requires support
151//! for integer overflows/underflows, and you prefer to handle it differently.
152//!
153//! ### Floating Point Numbers
154//!
155//! Support is available for the following primitive IEEE 754-2008 floating point types:
156//!
157//! - [`f32`]
158//! - [`f64`]
159//!
160//! ### Complex Numbers
161//!
162//! The [`Vector`] type supports **collections of** complex scalars as
163//! represented by the [`num::Complex`] type. Please review the num crate documentation
164//! for additional details on the [`num::Complex`] number type.
165//!
166//! **Note**: This guide will not provide detailed examples with [`num::Complex`] data in order to
167//! remain as concise as possible. With the notable exception of the
168//! floating point only [`Vector`] methods that can be identified with a [`num::Float`] trait bound,
169//! much of the public API supports the [`num::Complex`] type. These areas should be evident in the
170//! [`Vector`] API documentation descriptions and source trait bounds. [`num::Complex`] support
171//! *should* be available when a general [`num::Num`] trait bound is used in
172//! the implementation. In these cases, you can replace integer or floating point
173//! numbers in the following examples with [`num::Complex`] types. Please raise an
174//! issue on the repository if this is not the case.
175//!
176//! ## Initialization
177//!
178//! A [`Vector`] can have mutable values, but it cannot grow in length. The
179//! dimension length is fixed at instantiation, and all fields are *initialized*
180//! at instantiation. The maximum dimension length is [`usize::MAX`].
181//!
182//! The [`crate::vector`] macro is available for shorthand initialization of the [`Vector`] type
183//! with standard library [`array`]-like syntax.
184//!
185//! ### Zero Vector
186//!
187//! Use the [`Vector::zero`] method to initialize a [`Vector`] with zero values
188//! of the respective numeric type:
189//!
190//! ```
191//! use vectora::Vector;
192//!
193//! let v_zero_int: Vector<i32, 3> = Vector::zero();
194//!
195//! let v_zero_float: Vector<f64, 2> = Vector::zero();
196//!
197//! // Note: the following complex number example requires an import of the `num::Complex` type!
198//! use num::Complex;
199//!
200//! let v_zero_complex: Vector<Complex<f64>, 2> = Vector::zero();
201//! ```
202//!
203//! ### With Predefined Data in Other Types
204//!
205//! Use the [`Vector::from`] method or the [`crate::vector`] macro
206//! with an ordered [`array`] of data when possible:
207//!
208//! ```
209//! use vectora::{vector, Vector};
210//!
211//! // example three dimensional f64 Vector
212//! let v: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
213//! let v_alt = vector![1.0_f64, 2.0_f64, 3.0_f64];
214//!
215//! // example two dimensional i32 Vector
216//! let v: Vector<i32, 2> = Vector::from([4, -5]);
217//! let v_alt = vector![4_i32, -5_i32];
218//!
219//! // with num crate Complex numbers
220//! // Note: the following complex number example requires an import of the `num::Complex` type!
221//! use num::Complex;
222//!
223//! let v: Vector<Complex<f64>, 2> = Vector::from([Complex::new(1.0, 2.0), Complex::new(3.0, 4.0)]);
224//! let v_alt = vector![Complex::new(1.0_f64, 2.0_f64), Complex::new(3.0_f64, 4.0_f64)];
225//!
226//! // with a library type alias
227//! use vectora::types::vector::Vector3dF64;
228//!
229//! let v: Vector3dF64 = Vector::from([1.0, 2.0, 3.0]);
230//! let v_alt: Vector3dF64 = vector![1.0, 2.0, 3.0];
231//! ```
232//!
233//! or use one of the alternate initialization approaches with data
234//! in iterator, [`array`], [`slice`], or [`Vec`] types. The
235//! [`crate::try_vector`] macro is a shorthand approach to fallible
236//! initialization with data in these standard library types.
237//!
238//! ```
239//! use vectora::{try_vector, Vector};
240//!
241//! // from an iterator over an array or Vec with collect
242//! let v: Vector<i32, 3> = [1, 2, 3].into_iter().collect();
243//! let v: Vector<f64, 2> = vec![1.0, 2.0].into_iter().collect();
244//!
245//! // from a standard lib slice type with the try_from function or try_vector! macro
246//! let arr = [1, 2, 3];
247//! let vec = vec![1.0, 2.0, 3.0];
248//!
249//! let v: Vector<i32, 3> = Vector::try_from(&arr[..]).unwrap();
250//! let v_alt: Vector<i32, 3> = try_vector!(&arr[..]).unwrap();
251//!
252//! let v: Vector<f64, 3> = Vector::try_from(&vec[..]).unwrap();
253//! let v_alt: Vector<f64, 3> = try_vector!(&vec[..]).unwrap();
254//!
255//! // from a standard lib Vec type with the try_from function or try_vector! macro
256//! let vec = vec![1, 2, 3];
257//!
258//! let v: Vector<i32, 3> = Vector::try_from(&vec).unwrap();
259//! let v_alt: Vector<i32, 3> = try_vector!(&vec).unwrap();
260//! ```
261//!
262//! Please see the API docs for more information about overflow and underflow handling with the
263//! [`FromIterator`](types/vector/struct.Vector.html#impl-FromIterator<T>)
264//! trait implementation that supports the `collect` approach, and additional
265//! information about returned error types for fallible initializations.
266//!
267//! ## Numeric Type Casts
268//!
269//! Use the `to_[TYPE SIGNATURE]` methods for explicit [`Vector`] data type casts
270//! to supported integer and floating point types. Casts to unsupported numeric
271//! types (e.g., signed integer to unsigned integer) return `None`. Casts from
272//! unsupported types (e.g., [`num::Complex`] number with a non-zero imaginary part)
273//! return `None`.
274//!
275//! ```
276//! # use vectora::Vector;
277//! use num::Complex;
278//!
279//! let v_u8: Vector<u8, 3> = Vector::from([1, 2, 3]);
280//! let v_i8: Vector<i8, 3> = Vector::from([-1, 2, 3]);
281//! let v_complex: Vector<Complex<f32>, 2> = Vector::from([Complex::new(1.0, 0.0), Complex::new(2.0, 0.0)]);
282//!
283//! let v_i32: Vector<i32, 3> = v_u8.to_i32().unwrap();
284//! let v_f64: Vector<f64, 3> = v_u8.to_f64().unwrap();
285//! let v_f64_2: Vector<f64, 2> = v_complex.to_f64().unwrap();
286//!
287//! assert!(v_i8.to_u32().is_none());
288//! ```
289//!
290//! Implicit, lossless type casts can be performed between supported types
291//! with the `into` method:
292//!
293//! ```
294//! # use vectora::types::vector::Vector;
295//! let v_i32: Vector<i32, 2> = Vector::from([1_i32, 2_i32]);
296//!
297//! let v_i128: Vector<i128, 2> = v_i32.into();
298//! let v_f64: Vector<f64, 2> = v_i32.into();
299//! ```
300//!
301//! And the [`Vector::to_num_cast`] method supports unchecked, closure-defined
302//! type casts:
303//!
304//! ```
305//! # use vectora::types::vector::Vector;
306//! let v_i32: Vector<i32, 2> = Vector::from([1_i32, 2_i32]);
307//!
308//! let v_i128: Vector<i128, 2> = v_i32.to_num_cast(|x| x as i128);
309//! let v_f64: Vector<f64, 2> = v_i32.to_num_cast(|x| x as f64);
310//! ```
311//!
312//! Please review the API documentation for warnings and additional details.
313//!
314//! ## Access and Assignment with Indexing
315//!
316//! Use zero-based indices for access and assignment:
317//!
318//! ### Access
319//!
320//! ```
321//! # use vectora::Vector;
322//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
323//!
324//! let x = v1[0];
325//! let y = v1[1];
326//! let z = v1[2];
327//! ```
328//!
329//! Attempts to access items beyond the length of the [`Vector`] panic:
330//!
331//! ```should_panic
332//! # use vectora::Vector;
333//! # let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
334//! // panics!
335//! let _ = v1[10];
336//! ```
337//!
338//! ### Assignment
339//!
340//! ```
341//! # use vectora::Vector;
342//! let mut v1_m: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
343//!
344//! v1_m[0] = 10.0;
345//! v1_m[1] = 20.0;
346//! v1_m[2] = 30.0;
347//! ```
348//!
349//! Attempts to assign to items beyond the length of the [`Vector`] panic:
350//!
351//! ```should_panic
352//! # use vectora::Vector;
353//! # let mut v1_m: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
354//! // panics!
355//! v1_m[10] = 100.0;
356//! ```
357//!
358//! See the [`Vector::get`] and [`Vector::get_mut`] method documentation
359//! for getters that perform bounds checks and do not panic.
360//!
361//! ## Slicing
362//!
363//! Coerce to a read-only [`slice`] of the [`Vector`]:
364//!
365//! ```
366//! # use vectora::Vector;
367//! let v = Vector::<i32, 3>::from([1, 2, 3]);
368//! let v_slice = &v[0..2];
369//!
370//! assert_eq!(v_slice, [1, 2]);
371//! ```
372//!
373//! ## Partial Equivalence Testing
374//!
375//! Partial equivalence relation support is available with the `==` operator
376//! for integer, floating point, and [`num::Complex`] numeric types.
377//!
378//! ### Integer types
379//!
380//! [`Vector`] of real integer values:
381//!
382//! ```
383//! # use vectora::Vector;
384//! let v1: Vector<i32, 3> = Vector::from([10, 50, 100]);
385//! let v2: Vector<i32, 3> = Vector::from([5*2, 25+25, 10_i32.pow(2)]);
386//!
387//! assert!(v1 == v2);
388//! ```
389//!
390//! [`Vector`] of [`num::Complex`] numbers with integer real and imaginary parts:
391//!
392//! ```
393//! # use vectora::Vector;
394//! use num::Complex;
395//!
396//! let v1: Vector<Complex<i32>, 2> = Vector::from([Complex::new(1, 2), Complex::new(3, 4)]);
397//! let v2: Vector<Complex<i32>, 2> = Vector::from([Complex::new(1, 2), Complex::new(3, 4)]);
398//!
399//! assert!(v1 == v2);
400//! ```
401//!
402//! ### Float types
403//!
404//! We compare floating point types with the [approx](https://docs.rs/approx/latest/approx/)
405//! crate relative epsilon equivalence relation implementation by default. This includes
406//! fixed definitions of the epsilon and max relative difference values. See
407//! [the section below](#custom-equivalence-relations-for-float-types) for customization
408//! options with methods.
409//!
410//! Why a different strategy for floats?
411//!
412//! Some floating point numbers are not considered equivalent due to
413//! floating point precision:
414//!
415//! ```should_panic
416//! // panics!
417//! assert!(0.15_f64 + 0.15_f64 == 0.1_f64 + 0.2_f64);
418//! ```
419//!
420//! You likely want these floating point sums to compare as approximately equivalent.
421//!
422//! With the [`Vector`] type, they do.
423//!
424//! [`Vector`] of floating point values:
425//!
426//! ```
427//! # use vectora::Vector;
428//! let v1: Vector<f64, 1> = Vector::from([0.15 + 0.15]);
429//! let v2: Vector<f64, 1> = Vector::from([0.1 + 0.2]);
430//!
431//! assert!(v1 == v2);
432//! ```
433//!
434//! [`Vector`] of [`num::Complex`] numbers with floating point real and imaginary parts:
435//!
436//! ```
437//! # use vectora::Vector;
438//! use num::Complex;
439//!
440//! let v1: Vector<Complex<f64>, 2> = Vector::from([Complex::new(0.15 + 0.15, 2.0), Complex::new(3.0, 4.0)]);
441//! let v2: Vector<Complex<f64>, 2> = Vector::from([Complex::new(0.1 + 0.2, 2.0), Complex::new(3.0, 4.0)]);
442//!
443//! assert!(v1 == v2);
444//! ```
445//!
446//! `assert_eq!` and `assert_ne!` macro assertions use the same
447//! partial equivalence approach, as you'll note throughout these docs.
448//!
449//! You can implement the same equivalence relation approach for float types that
450//! are **not** contained in a [`Vector`] with the [approx crate](https://docs.rs/approx/latest/approx/)
451//! `relative_eq!`, `relative_ne!`, `assert_relative_eq!`, and `assert_relative_ne!`
452//! macros.
453//!
454//! ### Custom equivalence relations for floating point types
455//!
456//! The library also provides method support for absolute, relative, and units in last place (ULPs)
457//! approximate floating point equivalence relations. These methods allow custom epsilon, max relative,
458//! and max ULPs difference tolerances to define relations when float data are near and far apart. You
459//! must call the method to use them. It is not possible to modify the default approach used in the
460//! `==` operator overload.
461//!
462//! See the API documentation for [`Vector`] implementations of the `approx` crate `AbsDiffEq`, `RelativeEq`,
463//! `UlpsEq` traits in the links below:
464//!
465//! #### Absolute difference equivalence relation
466//!
467//! The absolute difference equivalence relation approach supports custom epsilon tolerance definitions.
468//!
469//! - [`Vector::abs_diff_eq`](types/vector/struct.Vector.html#impl-AbsDiffEq<Vector<f32%2C%20N>>) (`f32`)
470//! - [`Vector::abs_diff_eq`](types/vector/struct.Vector.html#impl-AbsDiffEq<Vector<f64%2C%20N>>) (`f64`)
471//! - [`Vector::abs_diff_eq`](types/vector/struct.Vector.html#impl-AbsDiffEq<Vector<Complex<f32>%2C%20N>>) (`Complex<f32>`)
472//! - [`Vector::abs_diff_eq`](types/vector/struct.Vector.html#impl-AbsDiffEq<Vector<Complex<f64>%2C%20N>>) (`Complex<f64>`)
473//!
474//! #### Relative difference equivalence relation
475//!
476//! The relative difference equivalence relation approach supports custom epsilon (data that are near)
477//! and max relative difference (data that are far apart) tolerance definitions.
478//!
479//! - [`Vector::relative_eq`](types/vector/struct.Vector.html#impl-RelativeEq<Vector<f32%2C%20N>>) (`f32`)
480//! - [`Vector::relative_eq`](types/vector/struct.Vector.html#impl-RelativeEq<Vector<f64%2C%20N>>) (`f64`)
481//! - [`Vector::relative_eq`](types/vector/struct.Vector.html#impl-RelativeEq<Vector<Complex<f32>%2C%20N>>) (`Complex<f32>`)
482//! - [`Vector::relative_eq`](types/vector/struct.Vector.html#impl-RelativeEq<Vector<Complex<f64>%2C%20N>>) (`Complex<f64>`)
483//!
484//! #### Units in Last Place (ULPs) difference equivalence relation
485//!
486//! The ULPs difference equivalence relation approach supports custom epsilon (data that are near)
487//! and max ULPs difference (data that are far apart) tolerance definitions.
488//!
489//! - [`Vector::ulps_eq`](types/vector/struct.Vector.html#impl-UlpsEq<Vector<f32%2C%20N>>) (`f32`)
490//! - [`Vector::ulps_eq`](types/vector/struct.Vector.html#impl-UlpsEq<Vector<f64%2C%20N>>) (`f64`)
491//! - [`Vector::ulps_eq`](types/vector/struct.Vector.html#impl-UlpsEq<Vector<Complex<f32>%2C%20N>>) (`Complex<f32>`)
492//! - [`Vector::ulps_eq`](types/vector/struct.Vector.html#impl-UlpsEq<Vector<Complex<f64>%2C%20N>>) (`Complex<f64>`)
493//!
494//! ## Iteration and Loops
495//!
496//! ### Over immutable scalar references
497//!
498//! ```
499//! # use vectora::Vector;
500//! let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
501//! let mut iter = v.iter();
502//!
503//! assert_eq!(iter.next(), Some(&-1));
504//! assert_eq!(iter.next(), Some(&2));
505//! assert_eq!(iter.next(), Some(&3));
506//! assert_eq!(iter.next(), None);
507//! ```
508//!
509//! The syntax for a loop over this type:
510//!
511//! ```
512//! # use vectora::Vector;
513//! # let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
514//! for x in &v {
515//! // do things
516//! }
517//! ```
518//!
519//! ### Over mutable scalar references
520//!
521//! ```
522//! # use vectora::Vector;
523//! let mut v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
524//! let mut iter = v.iter_mut();
525//!
526//! assert_eq!(iter.next(), Some(&mut -1));
527//! assert_eq!(iter.next(), Some(&mut 2));
528//! assert_eq!(iter.next(), Some(&mut 3));
529//! assert_eq!(iter.next(), None);
530//! ```
531//!
532//! The syntax for a loop over this type:
533//!
534//! ```
535//! # use vectora::Vector;
536//! # let mut v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
537//! for x in &mut v {
538//! // do things
539//! }
540//! ```
541//!
542//! ### Over mutable scalar values
543//!
544//! ```
545//! # use vectora::Vector;
546//! let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
547//! let mut iter = v.into_iter();
548//!
549//! assert_eq!(iter.next(), Some(-1));
550//! assert_eq!(iter.next(), Some(2));
551//! assert_eq!(iter.next(), Some(3));
552//! assert_eq!(iter.next(), None);
553//! ```
554//!
555//! The syntax for a loop over this type:
556//!
557//! ```
558//! # use vectora::Vector;
559//! # let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
560//! for x in v {
561//! // do things
562//! }
563//! ```
564//!
565//! ### Parallel iteration (Optional crate feature)
566//!
567//! *Optional* rayon parallel iterator support may be installed with the vectora crate
568//! `parallel` feature. With activation of this feature, you may use the `Vector::into_par_iter`,
569//! `Vector::par_iter`, or `Vector::par_iter_mut` methods to create a parallel iterator over owned
570//! [`Vector`] scalars or scalar references. The `parallel` feature provides access to the
571//! [rayon parallel iterator API](https://docs.rs/rayon/latest/rayon/iter/trait.ParallelIterator.html#provided-methods).
572//!
573//! See the [Optional Crate Features](#optional-crate-features) section above for
574//! installation instructions and refer to the [`Vector`] API docs for additional details.
575//!
576//! ## Vector Arithmetic
577//!
578//! Use operator overloads for vector arithmetic:
579//!
580//! ### Unary Negation
581//!
582//! The unary negation operator yields the additive inverse
583//! [`Vector`]:
584//!
585//! ```
586//! # use vectora::Vector;
587//! let v: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
588//!
589//! assert_eq!(-v, Vector::from([-1.0, -2.0, -3.0]));
590//! assert_eq!(v + -v, Vector::<f64, 3>::zero());
591//! ```
592//!
593//! ### Vector Addition
594//!
595//! ```
596//! # use vectora::Vector;
597//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
598//! let v2: Vector<f64, 3> = Vector::from([4.0, 5.0, 6.0]);
599//!
600//! let v3 = v1 + v2;
601//!
602//! assert_eq!(v3, Vector::from([5.0, 7.0, 9.0]));
603//! ```
604//!
605//! ### Vector Subtraction
606//!
607//! ```
608//! # use vectora::Vector;
609//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
610//! let v2: Vector<f64, 3> = Vector::from([4.0, 5.0, 6.0]);
611//!
612//! let v3 = v2 - v1;
613//!
614//! assert_eq!(v3, Vector::from([3.0, 3.0, 3.0]));
615//! ```
616//!
617//! ### Scalar Multiplication
618//!
619//! ```
620//! # use vectora::Vector;
621//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
622//! let v2: Vector<f64, 3> = Vector::from([4.0, 5.0, 6.0]);
623//!
624//! let v3 = v1 * 10.0;
625//! let v4 = v2 * -1.0;
626//!
627//! assert_eq!(v3, Vector::from([10.0, 20.0, 30.0]));
628//! assert_eq!(v4, Vector::from([-4.0, -5.0, -6.0]));
629//! ```
630//!
631//! #### Scalar multiplication with [`num::Complex`] numbers
632//!
633//! [`Vector`] of [`num::Complex`] types support multiplication with
634//! real and complex numbers.
635//!
636//! ##### [`num::Complex`] * real
637//!
638//! ```
639//! # use vectora::Vector;
640//! use num::Complex;
641//!
642//! let v: Vector<Complex<i32>, 2> = Vector::from([Complex::new(1, 2), Complex::new(3, 4)]);
643//!
644//! assert_eq!(v * 10, Vector::<Complex<i32>, 2>::from([Complex::new(10, 20), Complex::new(30, 40)]));
645//! ```
646//!
647//! ##### [`num::Complex`] * [`num::Complex`]
648//!
649//! ```
650//! # use vectora::Vector;
651//! use num::Complex;
652//!
653//! let v: Vector<Complex<f64>, 2> = Vector::from([Complex::new(3.0, 2.0), Complex::new(-3.0, -2.0)]);
654//! let c: Complex<f64> = Complex::new(1.0, 7.0);
655//!
656//! assert_eq!(v * c, Vector::from([Complex::new(-11.0, 23.0), Complex::new(11.0, -23.0)]));
657//! ```
658//!
659//! ## Methods for Vector Operations
660//!
661//! Method support is available for common vector calculations.
662//! Examples of some frequently used operations are shown below:
663//!
664//! ### Dot product
665//!
666//! ```
667//! # use vectora::Vector;
668//! use approx::assert_relative_eq;
669//!
670//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
671//! let v2: Vector<f64, 3> = Vector::from([4.0, 5.0, 6.0]);
672//!
673//! let dot_prod = v1.dot(&v2);
674//!
675//! assert_relative_eq!(dot_prod, 32.0);
676//! ```
677//!
678//! [ [API docs](types/vector/struct.Vector.html#method.dot) ]
679//!
680//! ### Vector Magnitude
681//!
682//! ```
683//! # use vectora::Vector;
684//! use approx::assert_relative_eq;
685//!
686//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
687//!
688//! let m = v1.magnitude();
689//!
690//! assert_relative_eq!(m, 3.7416573867739413);
691//! ```
692//!
693//! [ [API docs](types/vector/struct.Vector.html#method.magnitude) ]
694//!
695//! ### Vector Distance
696//!
697//! ```
698//! # use vectora::Vector;
699//! use approx::assert_relative_eq;
700//!
701//! let v1: Vector<f64, 2> = Vector::from([2.0, 2.0]);
702//! let v2: Vector<f64, 2> = Vector::from([4.0, 4.0]);
703//!
704//! assert_relative_eq!(v1.distance(&v2), 8.0_f64.sqrt());
705//! assert_relative_eq!(v1.distance(&v1), 0.0_f64);
706//! ```
707//!
708//! [ [API docs](types/vector/struct.Vector.html#method.distance) ]
709//!
710//! ### Opposite Vector
711//!
712//! ```
713//! # use vectora::Vector;
714//! use approx::assert_relative_eq;
715//!
716//! let v: Vector<f64, 3> = Vector::from([2.0, 2.0, 2.0]);
717//!
718//! assert_eq!(v.opposite(), Vector::from([-2.0, -2.0, -2.0]));
719//! assert_relative_eq!(v.opposite().magnitude(), v.magnitude());
720//! ```
721//!
722//! [ [API docs](types/vector/struct.Vector.html#method.opposite) ]
723//!
724//! ### Normalization
725//!
726//! ```
727//! # use vectora::Vector;
728//! use approx::assert_relative_eq;
729//!
730//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
731//!
732//! let unit_vector = v1.normalize();
733//!
734//! assert_relative_eq!(unit_vector.magnitude(), 1.0);
735//! ```
736//!
737//! [ [API docs](types/vector/struct.Vector.html#method.normalize) ]
738//!
739//! ### Linear Interpolation
740//!
741//!```
742//! # use vectora::Vector;
743//! let v1: Vector<f64, 3> = Vector::from([1.0, 2.0, 3.0]);
744//! let v2: Vector<f64, 3> = Vector::from([4.0, 5.0, 6.0]);
745//!
746//! let v3 = v1.lerp(&v2, 0.5).unwrap();
747//!
748//! assert_eq!(v3, Vector::from([2.5, 3.5, 4.5]));
749//!```
750//!
751//! [ [API docs](types/vector/struct.Vector.html#method.lerp) ]
752//!
753//! ### Closure Mapping
754//!
755//! ```
756//! # use vectora::Vector;
757//! let v1: Vector<f64, 3> = Vector::from([-1.0, 2.0, 3.0]);
758//!
759//! let v3 = v1.map_closure(|x| x.powi(2));
760//!
761//! assert_eq!(v3, Vector::from([1.0, 4.0, 9.0]));
762//! ```
763//!
764//! [ [API docs](types/vector/struct.Vector.html#method.map_closure) ]
765//!
766//! ### Function Mapping
767//!
768//!```
769//!# use vectora::Vector;
770//! let v1: Vector<f64, 3> = Vector::from([-1.0, 2.0, 3.0]);
771//!
772//! fn square(x: f64) -> f64 {
773//! x.powi(2)
774//! }
775//!
776//! let v3 = v1.map_fn(square);
777//!
778//! assert_eq!(v3, Vector::from([1.0, 4.0, 9.0]));
779//!```
780//!
781//! [ [API docs](types/vector/struct.Vector.html#method.map_fn) ]
782//!
783//! Many of these methods have mutable alternates that edit the [`Vector`] data
784//! in place instead of allocating a new [`Vector`]. The mutable methods are
785//! prefixed with `mut_*`.
786//!
787//! See the [`Vector` method implementations](types/vector/struct.Vector.html#implementations) docs
788//! for the complete list of supported methods and additional examples.
789//!
790//! ## Descriptive Statistics
791//!
792//! Element-wise measures of central tendency and dispersion are available for floating
793//! point [`Vector`] types.
794//!
795//! ### Arithmetic Mean
796//!
797//! ```
798//! # use vectora::Vector;
799//! use approx::assert_relative_eq;
800//!
801//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
802//!
803//! assert_relative_eq!(v.mean().unwrap(), 3.5);
804//! ```
805//!
806//! ### Geometric mean
807//!
808//! ```
809//! # use vectora::Vector;
810//! use approx::assert_relative_eq;
811//!
812//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
813//!
814//! assert_relative_eq!(v.mean_geo().unwrap(), 2.993795165523909);
815//! ```
816//!
817//! ### Harmonic mean
818//!
819//! ```
820//! # use vectora::Vector;
821//! use approx::assert_relative_eq;
822//!
823//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
824//!
825//! assert_relative_eq!(v.mean_harmonic().unwrap(), 2.4489795918367347);
826//! ```
827//!
828//! ### Median
829//!
830//! ```
831//! # use vectora::Vector;
832//! use approx::assert_relative_eq;
833//!
834//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
835//!
836//! assert_relative_eq!(v.median().unwrap(), 3.5);
837//! ```
838//!
839//! ### Variance
840//!
841//! ```
842//! # use vectora::Vector;
843//! use approx::assert_relative_eq;
844//!
845//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
846//!
847//! // population variance
848//! assert_relative_eq!(v.variance(0.0).unwrap(), 2.9166666666666665);
849//!
850//! // sample variance (with Bessel's correction)
851//! assert_relative_eq!(v.variance(1.0).unwrap(), 3.5);
852//! ```
853//!
854//! ### Standard deviation
855//!
856//! ```
857//! # use vectora::Vector;
858//! use approx::assert_relative_eq;
859//!
860//! let v: Vector<f64, 6> = Vector::from([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
861//!
862//! // population standard deviation
863//! assert_relative_eq!(v.stddev(0.0).unwrap(), 1.707825127659933);
864//!
865//! // sample standard deviation (with Bessel's correction)
866//! assert_relative_eq!(v.stddev(1.0).unwrap(), 1.8708286933869707);
867//! ```
868//!
869//! ## Working with Rust Standard Library Types
870//!
871//! Casts to commonly used Rust standard library data collection types are straightforward.
872//! Note that some of these type casts support mutable [`Vector`] owned data references,
873//! allowing you to use standard library type operations to change the [`Vector`] data.
874//!
875//! ### [`array`] Representations
876//!
877//! Immutable:
878//!
879//! ```
880//! # use vectora::Vector;
881//! let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
882//!
883//! assert_eq!(v.as_array(), &[-1, 2, 3]);
884//! assert_eq!(v.to_array(), [-1, 2, 3]);
885//! ```
886//!
887//! Mutable:
888//!
889//! ```
890//! # use vectora::Vector;
891//! let mut v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
892//!
893//! let m_arr = v.as_mut_array();
894//!
895//! assert_eq!(m_arr, &mut [-1, 2, 3]);
896//!
897//! m_arr[0] = -10;
898//!
899//! assert_eq!(m_arr, &mut [-10, 2, 3]);
900//! assert_eq!(v, Vector::from([-10, 2, 3]));
901//! ```
902//!
903//! ### [`slice`] Representations
904//!
905//! Immutable:
906//!
907//! ```
908//! # use vectora::Vector;
909//! let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
910//!
911//! assert_eq!(v.as_slice(), &[-1, 2, 3][..]);
912//! ```
913//!
914//! Mutable:
915//!
916//! ```
917//! # use vectora::Vector;
918//! let mut v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
919//!
920//! let m_sli = v.as_mut_slice();
921//!
922//! assert_eq!(m_sli, &mut [-1, 2, 3][..]);
923//!
924//! m_sli[0] = -10;
925//!
926//! assert_eq!(m_sli, &mut [-10, 2, 3]);
927//! assert_eq!(v, Vector::from([-10, 2, 3]));
928//! ```
929//!
930//!
931//! ### [`Vec`] Representations
932//!
933//! Casts to [`Vec`] always allocate a new [`Vec`] with copied data.
934//!
935//! ```
936//! # use vectora::Vector;
937//! let v: Vector<i32, 3> = Vector::from([-1, 2, 3]);
938//!
939//! assert_eq!(v.to_vec(), vec![-1, 2, 3]);
940//! ```
941//!
942//! See the [Initialization](#initialization) section for documentation of
943//! the syntax to instantiate a [`Vector`] from a standard library [`Vec`] type.
944
945#![warn(missing_docs)]
946#![deny(rustdoc::broken_intra_doc_links, unsafe_code)]
947
948pub mod errors;
949pub mod types;
950
951pub use types::vector::Vector;