al_jabr/lib.rs
1// Copyright 2019 The Al_Jabr Developers. For a full listing of authors,
2// refer to the Cargo.toml file at the top-level directory of this distribution.
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9//
10//! A generic linear algebra library for computer graphics.
11//!
12//! `al_jabr` is roughly compatible with [cgmath](https://github.com/rustgd/cgmath)
13//! and is intended to provide a small set of lightweight linear algebra
14//! operations typically useful in interactive computer graphics.
15//!
16//! `al_jabr` is n-dimensional, meaning that its data structures support an
17//! arbitrary number of elements. If you wish to create a five-dimensional rigid
18//! body simulation, `al_jabr` can help you.
19//!
20//! ## Getting started
21//!
22//! All of `al_jabr`'s types are exported in the root of the crate, so importing
23//! them all is as easy as adding the following to the top of your source file:
24//!
25//! ```
26//! use al_jabr::*;
27//! ```
28//!
29//! After that, you can begin using `al_jabr`.
30//!
31//! ### Vectors
32//!
33//! Small (N = 1, 2, 3, 4) vectors as well as an N-dimensional [ColumnVector] are
34//! provided. Unless you have a need for larger vectors, it is recommended to use
35//! [Vector1], [Vector2], [Vector3] or [Vector4].
36//!
37//! [Add], [Sub], and [Neg] will be properly implemented for any `Vector` and
38//! `ColumnVector<Scalar, N>` for any respective implementation of such operations
39//! for `Scalar`. Operations are only implemented for vectors of equal sizes.
40//!
41//! ```
42//! # use al_jabr::*;
43//! let a = Vector4::new(0.0f32, 1.0, 2.0, 3.0);
44//! let b = Vector4::new(1.0f32, 1.0, 1.0, 1.0);
45//! assert_eq!(
46//! a + b,
47//! Vector4::new(1.0, 2.0, 3.0, 4.0),
48//! );
49//!
50//! let d = column_vector![ 0.0f32, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, ];
51//! let e = column_vector![ 1.0f32, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, ] * 0.5;
52//! assert_eq!(
53//! d + e,
54//! column_vector![ 0.5f32, 1.5, 2.5, 3.5, 4.5, 5.5, 6.5 ]
55//! );
56//! ```
57//!
58//! If the scalar type implements [Mul] as well, then the Vector will be an
59//! [InnerSpace] and have the [dot](InnerSpace::dot) product defined for it,
60//! as well as the ability to find the squared distance between two vectors
61//! (implements [MetricSpace]) and the squared magnitude of a vector. If the
62//! scalar type is a real number then the distance between two vectors and
63//! the magnitude of a vector can be found in addition:
64//!
65//! ```rust
66//! # use al_jabr::*;
67//! let a = Vector2::new(1i32, 1);
68//! let b = Vector2::new(5i32, 5);
69//! assert_eq!(a.distance2(b), 32); // distance method not implemented.
70//! assert_eq!((b - a).magnitude2(), 32); // magnitude method not implemented.
71//!
72//! let a = Vector2::new(1.0f32, 1.0);
73//! let b = Vector2::new(5.0f32, 5.0);
74//! const close: f32 = 5.65685424949;
75//! assert_eq!(a.distance(b), close); // distance is implemented.
76//! assert_eq!((b - a).magnitude(), close); // magnitude is implemented.
77//!
78//! // Vector normalization is also supported for floating point scalars.
79//! assert_eq!(
80//! Vector3::new(0.0f32, 20.0, 0.0)
81//! .normalize(),
82//! Vector3::new(0.0f32, 1.0, 0.0)
83//! );
84//! ```
85//!
86//! #### Swizzling
87//!
88//! ColumnVectors of any size and Vectors of size 2, 3 and 4 support
89//! [swizzling](https://en.wikipedia.org/wiki/Swizzling_(computer_graphics)).
90//! The methods are hidden as to not pollute the docs, but are still available:
91//!
92//! ```rust
93//! # use al_jabr::*;
94//! assert_eq!(Vector3::new(1i32, 2, 3).xy(), Vector2::new(1i32, 2));
95//! ```
96//!
97//! ### Points
98//!
99//! Small (N = 1, 2, 3, 4) points in space are provided.
100//!
101//! Points are far less flexible and useful than vectors and are used
102//! to express the purpose or meaning of a variable through its type.
103//!
104//! Points can be moved through space by adding or subtracting Vectors from
105//! them.
106//!
107//! The only mathematical operator supported between two points is
108//! subtraction, which results in the vector between the two points.
109//!
110//! Points can be freely converted to and from vectors via `from_vec`
111//! and `to_vec`.
112//!
113//! ```rust
114//! # use al_jabr::*;
115//! let a = Point3::new(5, 4, 3);
116//! let b = Point3::new(1, 1, 1);
117//! assert_eq!(a - b, Vector3::new(4, 3, 2));
118//! ```
119//!
120//! ### Matrices
121//!
122//! [Matrices](Matrix) can be created from an array of arrays of any size
123//! and scalar type. Matrices are column-major and constructing a matrix from a
124//! raw array reflects that. The [matrix!] macro can be used to construct a
125//! matrix in row-major order:
126//!
127//! ```
128//! # use al_jabr::*;
129//! // Construct in column-major order:
130//! let a = Matrix::<i32, 3, 3>::from([
131//! [ 0, 6, 2 ],
132//! [ -3, 1, 3 ],
133//! [ 5, -4, -2 ],
134//! ]);
135//!
136//! // Construct in row-major order:
137//! let b: Matrix::<i32, 3, 3> = matrix![
138//! [ 0, -3, 5 ],
139//! [ 6, 1, -4 ],
140//! [ 2, 3, -2 ]
141//! ];
142//!
143//! assert_eq!(a, b);
144//! ```
145//!
146//! All operations performed on matrices produce fixed-size outputs. For
147//! example, taking the [transpose](Matrix::transpose) of a non-square matrix
148//! will produce a matrix with the width and height swapped:
149//!
150//! ```
151//! # use al_jabr::*;
152//! assert_eq!(
153//! Matrix::<i32, 1, 2>::from([ [ 1 ], [ 2 ] ])
154//! .transpose(),
155//! Matrix::<i32, 2, 1>::from([ [ 1, 2 ] ])
156//! );
157//! ```
158//!
159//! As with Vectors, if the underlying scalar type supports the appropriate
160//! operations, a matrix will implement element-wise [Add] and [Sub] for
161//! matrices of equal size:
162//!
163//! ```
164//! # use al_jabr::*;
165//! let a = matrix!([1_u32]);
166//! let b = matrix!([2_u32]);
167//! let c = matrix!([3_u32]);
168//! assert_eq!(a + b, c);
169//! ```
170//!
171//! And this is true for any type that implements [Add], so therefore the
172//! following is possible as well:
173//!
174//! ```
175//! # use al_jabr::*;
176//! let a = matrix!([matrix!([1_u32])]);
177//! let b = matrix!([matrix!([2_u32])]);
178//! let c = matrix!([matrix!([3_u32])]);
179//! assert_eq!(a + b, c);
180//! ```
181//!
182//! For a given type `T`, if `T: Clone` and `Vector<T, _>` is an [InnerSpace],
183//! then multiplication is defined for `Matrix<T, N, M> * Matrix<T, M, P>`. The
184//! result is a `Matrix<T, N, P>`:
185//!
186//! ```rust
187//! # use al_jabr::*;
188//! let a: Matrix::<i32, 3, 3> = matrix![
189//! [ 0, -3, 5 ],
190//! [ 6, 1, -4 ],
191//! [ 2, 3, -2 ],
192//! ];
193//! let b: Matrix::<i32, 3, 3> = matrix![
194//! [ -1, 0, -3 ],
195//! [ 4, 5, 1 ],
196//! [ 2, 6, -2 ],
197//! ];
198//! let c: Matrix::<i32, 3, 3> = matrix![
199//! [ -2, 15, -13 ],
200//! [ -10, -19, -9 ],
201//! [ 6, 3, 1 ],
202//! ];
203//! assert_eq!(
204//! a * b,
205//! c
206//! );
207//! ```
208//!
209//! Some matrices have special functions defined for them. Check out [Matrix3]
210//! and [Matrix4] for more information.
211
212use core::{
213 cmp::PartialOrd,
214 fmt,
215 hash::{Hash, Hasher},
216 iter::{FromIterator, Product},
217 marker::PhantomData,
218 mem::{self, transmute_copy, MaybeUninit},
219 ops::{
220 Add, AddAssign, Deref, DerefMut, Div, DivAssign, Index, IndexMut, Mul, MulAssign, Neg, Sub,
221 SubAssign,
222 },
223};
224
225#[cfg(feature = "rand")]
226use rand::{
227 distributions::{Distribution, Standard},
228 Rng,
229};
230
231#[cfg(feature = "serde")]
232use serde::{
233 de::{Error, SeqAccess, Visitor},
234 ser::SerializeTuple,
235 Deserialize, Deserializer, Serialize, Serializer,
236};
237
238mod array;
239mod column_vector;
240mod matrix;
241mod point;
242mod rotation;
243pub mod row_view;
244mod vector;
245
246pub use array::*;
247pub use column_vector::*;
248pub use matrix::*;
249pub use point::*;
250pub use rotation::*;
251use row_view::*;
252pub use vector::*;
253
254/// Defines the additive identity for `Self`.
255pub trait Zero {
256 /// Returns the additive identity of `Self`.
257 fn zero() -> Self;
258
259 /// Returns true if the value is the additive identity.
260 fn is_zero(&self) -> bool;
261}
262
263macro_rules! impl_zero {
264 // Default $zero to '0' if not provided.
265 (
266 $type:ty
267 ) => {
268 impl_zero! { $type, 0 }
269 };
270 // Main impl.
271 (
272 $type:ty,
273 $zero:expr
274 ) => {
275 impl Zero for $type {
276 fn zero() -> Self {
277 $zero
278 }
279
280 fn is_zero(&self) -> bool {
281 *self == $zero
282 }
283 }
284 };
285}
286
287impl_zero! { bool, false }
288impl_zero! { f32, 0.0 }
289impl_zero! { f64, 0.0 }
290impl_zero! { i8 }
291impl_zero! { i16 }
292impl_zero! { i32 }
293impl_zero! { i64 }
294impl_zero! { i128 }
295impl_zero! { isize }
296impl_zero! { u8 }
297impl_zero! { u16 }
298impl_zero! { u32 }
299impl_zero! { u64 }
300impl_zero! { u128 }
301impl_zero! { usize }
302
303/// Defines the multiplicative identity element for `Self`.
304///
305/// For Matrices, `one` is an alias for the unit matrix.
306pub trait One {
307 /// Returns the multiplicative identity for `Self`.
308 fn one() -> Self;
309
310 /// Returns true if the value is the multiplicative identity.
311 fn is_one(&self) -> bool;
312}
313
314macro_rules! impl_one {
315 // Default $one to '1' if not provided.
316 (
317 $type:ty
318 ) => {
319 impl_one! { $type, 1 }
320 };
321 // Main impl.
322 (
323 $type:ty,
324 $one:expr
325 ) => {
326 impl One for $type {
327 fn one() -> Self {
328 $one
329 }
330
331 fn is_one(&self) -> bool {
332 *self == $one
333 }
334 }
335 };
336}
337
338impl_one! { bool, true }
339impl_one! { f32, 1.0 }
340impl_one! { f64, 1.0 }
341impl_one! { i8 }
342impl_one! { i16 }
343impl_one! { i32 }
344impl_one! { i64 }
345impl_one! { i128 }
346impl_one! { isize }
347impl_one! { u8 }
348impl_one! { u16 }
349impl_one! { u32 }
350impl_one! { u64 }
351impl_one! { u128 }
352impl_one! { usize }
353
354/// Values that are [real numbers](https://en.wikipedia.org/wiki/Real_number#Axiomatic_approach).
355pub trait Real
356where
357 Self: Sized,
358 Self: Add<Output = Self>,
359 Self: Sub<Output = Self>,
360 Self: Mul<Output = Self>,
361 Self: Div<Output = Self>,
362 Self: Neg<Output = Self>,
363 Self: PartialOrd + PartialEq,
364{
365 fn sqrt(self) -> Self;
366
367 /// Returns twice the value.
368 fn mul2(self) -> Self;
369
370 /// Returns half of the value.
371 fn div2(self) -> Self;
372
373 fn abs(self) -> Self;
374
375 /// Returns the sine of the angle.
376 fn sin(self) -> Self;
377
378 /// Returns the cosine of the angle.
379 fn cos(self) -> Self;
380
381 /// Returns the tangent of the angle.
382 fn tan(self) -> Self;
383
384 /// Returns the arcsine of the angle.
385 fn asin(self) -> Self;
386
387 /// Returns the arccos of the angle.
388 fn acos(self) -> Self;
389
390 /// Returns the four quadrant arctangent of `self` and `x` in radians.
391 fn atan2(self, x: Self) -> Self;
392
393 /// Returns the sine and the cosine of the angle.
394 fn sin_cos(self) -> (Self, Self);
395
396 /// Returns the sign of the number.
397 fn signum(self) -> Self;
398}
399
400impl Real for f32 {
401 fn sqrt(self) -> Self {
402 self.sqrt()
403 }
404
405 fn mul2(self) -> Self {
406 2.0 * self
407 }
408
409 fn div2(self) -> Self {
410 self / 2.0
411 }
412
413 fn abs(self) -> Self {
414 self.abs()
415 }
416
417 fn sin(self) -> Self {
418 self.sin()
419 }
420
421 fn cos(self) -> Self {
422 self.cos()
423 }
424
425 fn asin(self) -> Self {
426 self.asin()
427 }
428
429 fn acos(self) -> Self {
430 self.acos()
431 }
432
433 fn tan(self) -> Self {
434 self.tan()
435 }
436
437 fn atan2(self, x: Self) -> Self {
438 self.atan2(x)
439 }
440
441 fn sin_cos(self) -> (Self, Self) {
442 (self.sin(), self.cos())
443 }
444
445 fn signum(self) -> Self {
446 self.signum()
447 }
448}
449
450impl Real for f64 {
451 fn sqrt(self) -> Self {
452 self.sqrt()
453 }
454
455 fn mul2(self) -> Self {
456 2.0 * self
457 }
458
459 fn div2(self) -> Self {
460 self / 2.0
461 }
462
463 fn abs(self) -> Self {
464 self.abs()
465 }
466
467 fn sin(self) -> Self {
468 self.sin()
469 }
470
471 fn cos(self) -> Self {
472 self.cos()
473 }
474
475 fn asin(self) -> Self {
476 self.asin()
477 }
478
479 fn acos(self) -> Self {
480 self.acos()
481 }
482
483 fn tan(self) -> Self {
484 self.tan()
485 }
486
487 fn atan2(self, x: Self) -> Self {
488 self.atan2(x)
489 }
490
491 fn sin_cos(self) -> (Self, Self) {
492 (self.sin(), self.cos())
493 }
494
495 fn signum(self) -> Self {
496 self.signum()
497 }
498}
499
500/// Vectors that can be added together and multiplied by scalars form a
501/// `VectorSpace`.
502///
503/// If a type implements [Add] and [Sub] and its scalar implements [Mul] and
504/// [Div], then that vector is part of a `VectorSpace`.
505pub trait VectorSpace
506where
507 Self: Sized + Clone + Zero,
508 Self: Add<Self, Output = Self>,
509 Self: Sub<Self, Output = Self>,
510 Self: Mul<<Self as VectorSpace>::Scalar, Output = Self>,
511 Self: Div<<Self as VectorSpace>::Scalar, Output = Self>,
512{
513 // I only need Div, but I felt like I had to add them all...
514 type Scalar: Add<Self::Scalar, Output = Self::Scalar>
515 + Sub<Self::Scalar, Output = Self::Scalar>
516 + Mul<Self::Scalar, Output = Self::Scalar>
517 + Div<Self::Scalar, Output = Self::Scalar>;
518
519 /// Linear interpolate between the two vectors with a weight of `t`.
520 fn lerp(self, other: Self, t: Self::Scalar) -> Self {
521 self.clone() + ((other - self) * t)
522 }
523}
524
525/// A type with a distance function between two values.
526pub trait MetricSpace: Sized {
527 type Metric;
528
529 /// Returns the distance squared between the two values.
530 fn distance2(self, other: Self) -> Self::Metric;
531}
532
533/// A [MetricSpace] where the metric is a real number.
534pub trait RealMetricSpace: MetricSpace
535where
536 Self::Metric: Real,
537{
538 /// Returns the distance between the two values.
539 fn distance(self, other: Self) -> Self::Metric {
540 self.distance2(other).sqrt()
541 }
542}
543
544impl<T> RealMetricSpace for T
545where
546 T: MetricSpace,
547 <T as MetricSpace>::Metric: Real,
548{
549}
550
551/// Vector spaces that have an inner (also known as "dot") product.
552pub trait InnerSpace: VectorSpace
553where
554 Self: Clone,
555 Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
556{
557 /// Return the inner (also known as "dot") product.
558 fn dot(self, other: Self) -> Self::Scalar;
559
560 /// Returns the squared length of the value.
561 fn magnitude2(self) -> Self::Scalar {
562 self.clone().dot(self)
563 }
564
565 /// Returns the [reflection](https://en.wikipedia.org/wiki/Reflection_(mathematics))
566 /// of the current vector with respect to the given surface normal. The
567 /// surface normal must be of length 1 for the return value to be
568 /// correct. The current vector is interpreted as pointing toward the
569 /// surface, and does not need to be normalized.
570 fn reflect(self, surface_normal: Unit<Self>) -> Self {
571 let surface_normal = surface_normal.into_inner();
572 let a = surface_normal.clone() * self.clone().dot(surface_normal);
573 self - (a.clone() + a)
574 }
575}
576
577/// Defines an [InnerSpace] where the Scalar is a real number. Automatically
578/// implemented.
579pub trait RealInnerSpace: InnerSpace
580where
581 Self: Clone,
582 Self: MetricSpace<Metric = <Self as VectorSpace>::Scalar>,
583 <Self as VectorSpace>::Scalar: Real,
584{
585 /// Returns the length of the vector.
586 fn magnitude(self) -> Self::Scalar {
587 self.clone().dot(self).sqrt()
588 }
589
590 /// Returns a vector with the same direction and a magnitude of `1`.
591 fn normalize(self) -> Self
592 where
593 Self::Scalar: One,
594 {
595 self.normalize_to(<Self::Scalar as One>::one())
596 }
597
598 /// Returns a vector with the same direction and a given magnitude.
599 fn normalize_to(self, magnitude: Self::Scalar) -> Self {
600 self.clone() * (magnitude / self.magnitude())
601 }
602
603 /// Returns the
604 /// [vector projection](https://en.wikipedia.org/wiki/Vector_projection)
605 /// of the current inner space projected onto the supplied argument.
606 fn project_on(self, other: Self) -> Self {
607 other.clone() * (self.dot(other.clone()) / other.magnitude2())
608 }
609}
610
611impl<T> RealInnerSpace for T
612where
613 T: InnerSpace,
614 <T as VectorSpace>::Scalar: Real,
615{
616}
617
618/// An object with a magnitude of one
619#[derive(Copy, Clone, Debug, PartialEq, Eq)]
620#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
621#[repr(transparent)]
622pub struct Unit<T>(T);
623
624impl<T> Unit<T> {
625 pub fn into_inner(self) -> T {
626 self.0
627 }
628}
629
630impl<T> Deref for Unit<T> {
631 type Target = T;
632
633 fn deref(&self) -> &Self::Target {
634 &self.0
635 }
636}
637
638impl<T> DerefMut for Unit<T> {
639 fn deref_mut(&mut self) -> &mut Self::Target {
640 &mut self.0
641 }
642}
643
644impl<T> Unit<T>
645where
646 T: RealInnerSpace + VectorSpace,
647 T::Scalar: Real + One,
648{
649 /// Construct a new unit object, normalizing the input in the process
650 pub fn new_normalize(obj: T) -> Self {
651 Unit(obj.normalize())
652 }
653}
654
655impl<T> Unit<T> {
656 /// Construct a new unit object without normalizing
657 ///
658 /// # Safety
659 ///
660 /// This method assumes that the object being passed to it is normalized,
661 /// i.e. has a magnitude of one. If it does not, other methods can break
662 /// in strange ways.
663 pub unsafe fn new_unchecked(obj: T) -> Self {
664 Unit(obj)
665 }
666}
667
668impl<T> Unit<T>
669where
670 T: RealInnerSpace + VectorSpace + Neg<Output = T>,
671 T::Scalar: Real + Zero + One + Clone,
672{
673 /// Perform a normalized linear interpolation between self and rhs
674 pub fn nlerp(self, mut rhs: Self, amount: T::Scalar) -> Self {
675 if self.0.clone().dot(rhs.0.clone()) < T::Scalar::zero() {
676 rhs.0 = -rhs.0;
677 }
678 Self::new_normalize(self.0 * (T::Scalar::one() - amount.clone()) + rhs.0 * amount)
679 }
680
681 /// Perform a spherical linear interpolation between self and rhs
682 pub fn slerp(self, mut rhs: Self, amount: T::Scalar) -> Self {
683 let mut dot = self.0.clone().dot(rhs.0.clone());
684
685 if dot.clone() < T::Scalar::zero() {
686 rhs.0 = -rhs.0;
687 dot = -dot;
688 }
689
690 if dot.clone() >= T::Scalar::one() {
691 return self;
692 }
693
694 let theta = dot.acos();
695 let scale_lhs = (theta.clone() * (T::Scalar::one() - amount.clone())).sin();
696 let scale_rhs = (theta * amount).sin();
697
698 Self::new_normalize(self.0 * scale_lhs + rhs.0 * scale_rhs)
699 }
700}
701
702/// Convert a object to a unit object
703pub trait IntoUnit: Sized {
704 fn into_unit(self) -> Unit<Self>;
705}
706
707impl<T> IntoUnit for T
708where
709 T: RealInnerSpace + VectorSpace,
710 T::Scalar: Real + One,
711{
712 fn into_unit(self) -> Unit<Self> {
713 Unit::new_normalize(self)
714 }
715}