### 9 releases

✓ Uses Rust 2018 edition

0.2.7 | Jul 9, 2019 |
---|---|

0.2.6 | Jul 9, 2019 |

0.2.5 | Jun 29, 2019 |

0.1.0 | Jun 21, 2019 |

#**29** in Math

**74** downloads per month

**GPL-3.0**license

72KB

1.5K
SLoC

# aljabar

An experimental n-dimensional linear algebra and mathematics library for the Rust programming language that makes extensive use of unstable Rust features.

aljabar supports Vectors and Matrices of any size and will provide implementations for any mathematic operations that are supported by their scalars. Additionally, aljabar can leverage Rust's type system to ensure that operations are only applied to values that are the correct size.

aljabar relies heavily on unstable Rust features such as const generics and thus requires nightly to build.

## Provided types

Currently, aljabar supports only

and `Vector`

types. Over the long
term aljabar is intended to be feature compliant with cgmath.`Matrix`

`Vector`

`Vector`

Vectors can be constructed from arrays of any type and size. There are convenience constructor functions provided for the most common sizes:

`let` a `=` `vec4``(` `0``u32``,` `1``,` `2``,` `3` `)``;`
`assert_eq!``(`
a`,`
`Vector``::``<``u32`, 4`>``::`from`(``[` `0``u32``,` `1``,` `2``,` `3` `]``)`
`)``;`

, `Add`

, and `Sub`

will be properly implemented for any `Neg`

for any respective implementation of such operations for `Vector <Scalar, N>`

`Scalar`

. Operations
are only implemented for vectors of equal sizes.`let` b `=` `Vector``::``<``f32`, 7`>``::`from`(``[` `0.``0``f32``,` `1.``0``,` `2.``0``,` `3.``0``,` `4.``0``,` `5.``0``,` `6.``0``,` `]``)``;`
`let` c `=` `Vector``::``<``f32`, 7`>``::`from`(``[` `1.``0``f32``,` `1.``0``,` `1.``0``,` `1.``0``,` `1.``0``,` `1.``0``,` `1.``0``,` `]``)` `*` `0.``5``;`
`assert_eq!``(`
b `+` c`,`
`Vector``::``<``f32`, 7`>``::`from`(``[` `0.``5``f32``,` `1.``5``,` `2.``5``,` `3.``5``,` `4.``5``,` `5.``5``,` `6.``5` `]``)`
`)``;`

If the scalar type implements

as well, then the Vector will be an
`Mul`

and have the `InnerSpace`

product defined for it, as well as the ability
to find the squared distance between two vectors (implements `dot`

) and
the squared magnitude of a vector. If the scalar type is a real number then the
distance between two vectors and the magnitude of a vector can be found in
addition:`MetricSpace`

`let` a `=` `vec2``(` `1``i32``,` `1``)``;`
`let` b `=` `vec2``(` `5``i32``,` `5` `)``;`
`assert_eq!``(`a`.``distance2``(`b`)``,` `32``)``;` `//` distance method not implemented.
`assert_eq!``(``(`b `-` a`)``.``magnitude2``(``)``,` `32``)``;` `//` magnitude method not implemented.
`let` a `=` `vec2``(` `1.``0``f32``,` `1.``0` `)``;`
`let` b `=` `vec2``(` `5.``0``f32``,` `5.``0` `)``;`
`const` close`:` `f32` `=` `5.``65685424949``;`
`assert_eq!``(`a`.``distance``(`b`)``,` close`)``;` `//` distance is implemented.
`assert_eq!``(``(`b `-` a`)``.``magnitude``(``)``,` close`)``;` `//` magnitude is implemented.
`//` Vector normalization is also supported for floating point scalars.
`assert_eq!``(`
`vec3``(` `0.``0``f32``,` `20.``0``,` `0.``0` `)`
`.``normalize``(``)``,`
`vec3``(` `0.``0``f32``,` `1.``0``,` `0.``0` `)`
`)``;`

#### Swizzling

Swizzling
is supported for both the

or `xyzw`

conventions. All possible combinations
of the first four elements of a vector are supported. Single-element swizzle
functions return scalar results, multi-element swizzle functions return vector
results of the appropriate size based on the number of selected elements.`rgba`

`let` a `=` `vec4``(``0.``0``f32``,` `1.``0``,` `2.``0``,` `3.``0` `)``;`
`//` A single element is returned as a scalar.
`assert_eq!``(``1.``0``,` a`.``y``(``)``)``;`
`//` Multiple elements are returned as a vector.
`assert_eq!``(``vec3``(``2.``0``,` `0.``0``,` `3.``0``)``,` a`.``zxw``(``)``)``;`
`//` The same element can be selected more than once.
`assert_eq!``(``vec2``(``0.``0``f32``,` `0.``0``)``,` a`.``rr``(``)``)``;`

Mixing

and `xyzw`

swizzle conventions is not allowed.`rgba`

`let` a `=` `vec4``(``0.``0``f32``,` `1.``0``,` `2.``0``,` `3.``0``)``;`
`let` b `=` a`.``rgzw``(``)``;` `//` Does not compile.

Swizzling is supported on vectors of length less than 4. Attempting to access elements past the length of the vector is a compile error.

`let` a `=` `vec3``(``0.``0``f32``,` `1.``0``,` `2.``0``)``;`
`let` b `=` a`.``xyz``(``)``;` `//` OK, only accesses the first 3 elements.
`let` c `=` a`.``rgba``(``)``;` `//` Compile error, attempts to access missing 4th element.

`Matrix`

`Matrix`

Matrices can be created from arrays of Vectors of any size and scalar type. As with Vectors there are convenience constructor functions for square matrices of the most common sizes:

`let` a `=` `Matrix``::``<``f32`, 3, 3`>``::`from`(` `[` `vec3``(` `1.``0``,` `0.``0``,` `0.``0` `)``,`
`vec3``(` `0.``0``,` `1.``0``,` `0.``0` `)``,`
`vec3``(` `0.``0``,` `0.``0``,` `1.``0` `)``,` `]` `)``;`
`let` b`:` `Matrix``::``<``i32`, 3, 3`>` `=`
`mat3x3``(` `0``,` `-``3``,` `5``,`
`6``,` `1``,` `-``4``,`
`2``,` `3``,` `-``2` `)``;`

All operations performed on matrices produce fixed-size outputs. For example,
taking the

of a non-square matrix will produce a matrix with the
width and height swapped:`transpose`

`assert_eq!``(`
`Matrix``::``<``i32`, 1, 2`>``::`from`(` `[` `vec1``(` `1` `)``,` `vec1``(` `2` `)` `]` `)`
`.``transpose``(``)``,`
`Matrix``::``<``i32`, 2, 1`>``::`from`(` `[` `vec2``(` `1``,` `2` `)` `]` `)`
`)``;`

As with Vectors, if the underlying scalar type supports the appropriate
operations, a

will implement element-wise `Matrix`

and `Add`

for matrices
of equal size:`Sub`

`let` a `=` `mat1x1``(` `1``u32` `)``;`
`let` b `=` `mat1x1``(` `2``u32` `)``;`
`let` c `=` `mat1x1``(` `3``u32` `)``;`
`assert_eq!``(`a `+` b`,` c`)``;`

And this is true for any type that implements

, so therefore the following
is possible as well:`Add`

`let` a `=` `mat1x1``(``mat1x1``(``1``u32``)``)``;`
`let` b `=` `mat1x1``(``mat1x1``(``2``u32``)``)``;`
`let` c `=` `mat1x1``(``mat1x1``(``3``u32``)``)``;`
`assert_eq!``(`a `+` b`,` c`)``;`

For a given type

, if `T`

and `T : Clone`

`Vector``<`T, `_``>`

is an `InnerSpace`

, then
multiplication is defined for `Matrix``<`T, N, M`>` `*` `Matrix``<`T, M, P`>`

. The result is
a `Matrix``<`T, N, P`>`

:`let` a`:` `Matrix``::``<``i32`, 3, 3`>` `=`
`mat3x3``(` `0``,` `-``3``,` `5``,`
`6``,` `1``,` `-``4``,`
`2``,` `3``,` `-``2` `)``;`
`let` b`:` `Matrix``::``<``i32`, 3, 3`>` `=`
`mat3x3``(` `-``1``,` `0``,` `-``3``,`
`4``,` `5``,` `1``,`
`2``,` `6``,` `-``2` `)``;`
`let` c`:` `Matrix``::``<``i32`, 3, 3`>` `=`
`mat3x3``(` `-``2``,` `15``,` `-``13``,`
`-``10``,` `-``19``,` `-``9``,`
`6``,` `3``,` `1` `)``;`
`assert_eq!``(`
a `*` b`,`
c
`)``;`

It is important to note that this implementation is not necessarily commutative.
That is because matrices only need to share one dimension in order to be
multiplied together in one direction. From this fact a somewhat pleasant trait
bound appears: matrices that satisfy `Mul <Self>`

*must*be square matrices. This is reflected by a matrix's trait bounds; if a Matrix is square, you are able to extract a diagonal vector from it:

`assert_eq!``(`
`mat3x3``(` `1``i32``,` `0``,` `0``,`
`0``,` `2``,` `0``,`
`0``,` `0``,` `3` `)`
`.``diagonal``(``)``,`
`vec3``(` `1``i32``,` `2``,` `3` `)`
`)``;`
`assert_eq!``(`
`mat4x4``(` `1``i32``,` `0``,` `0``,` `0``,`
`0``,` `2``,` `0``,` `0``,`
`0``,` `0``,` `3``,` `0``,`
`0``,` `0``,` `0``,` `4` `)`
`.``diagonal``(``)``,`
`vec4``(` `1``i32``,` `2``,` `3``,` `4` `)`
`)``;`

Matrices can be indexed by either their native column major storage or by
the more natural row major method. In order to use row-major indexing, call

or `.`index

on the matrix with a pair of indices. Calling
`.`index_mut

with a single index will produce a Vector representing the
appropriate column of the matrix.`.`index`.`

`let` m`:` `Matrix``::``<``i32`, 2, 2`>` `=`
`mat2x2``(` `0``,` `2``,`
`1``,` `3` `)``;`
`//` Column-major indexing:
`assert_eq!``(`m`[``0``]``[``0``]``,` `0``)``;`
`assert_eq!``(`m`[``0``]``[``1``]``,` `1``)``;`
`assert_eq!``(`m`[``1``]``[``0``]``,` `2``)``;`
`assert_eq!``(`m`[``1``]``[``1``]``,` `3``)``;`
`//` Row-major indexing:
`assert_eq!``(`m`[``(``0``,` `0``)``]``,` `0``)``;`
`assert_eq!``(`m`[``(``1``,` `0``)``]``,` `1``)``;`
`assert_eq!``(`m`[``(``0``,` `1``)``]``,` `2``)``;`
`assert_eq!``(`m`[``(``1``,` `1``)``]``,` `3``)``;`

## Provided traits

`Zero`

and `One`

`Zero`

`One`

Defines the additive and multiplicative identity respectively.

returns
vectors and matrices filled with zeroes, while `zero`

returns the unit matrix
and is unimplemented vectors.`one`

`Real`

`Real`

As far as aljabar is considered, a

is a value that has `Real`

defined.
By default this is implemented for `sqrt`

and `f32`

.`f64`

`VectorSpace`

`VectorSpace`

If a

implements `Vector`

and `Add`

and its scalar implements `Sub`

and
`Mul`

, then that vector is part of a `Div`

.`VectorSpace`

`MetricSpace`

`MetricSpace`

If two scalars have a distance squared, then vectors of that scalar type
implement

.`MetricSpace`

`RealMetricSpace`

`RealMetricSpace`

If a vector is a

and its scalar is a real number, then
`MetricSpace`

is defined as an alias for `.``distance``(``)``.``distance2``(``)``.``sqrt``(``)`

`InnerSpace`

`InnerSpace`

If a vector is a

, a `VectorSpace`

, and its scalar implements
`MetricSpace`

, then it is also an `Clone`

and has the inner product defined for
it. The inner product is known as the `InnerSpace`

product and its respective method
in aljabar takes that spelling.`dot`

A vector that is an

also has `InnerSpace`

implemented, which is
defined as the length of the vector squared.`.``magnitude2``(``)`

`RealInnerSpace`

`RealInnerSpace`

If a vector is an

and its scalar is a real number then it inherits
a number of convenience methods:`InnerSpace`

: returns the length of the vector.`.``magnitude``(``)`

: returns a vector with the same direction and a length of one.`.``normalize``(``)`

: returns a vector with the same direction and a length of`.``normalize_to``(`magnitude`)`

.`magnitude`

: returns the vector projection of the current inner space onto the given argument.`.``project_on``(`other`)`

`SquareMatrix`

`SquareMatrix`

A

that implements `Matrix`

. Square matrices have the following
methods defined for them:`Mul <Self>`

: returns the diaganol vector of the matrix.`.``diagonal``(``)`

: returns the determinant of the matrix.`.``determinant``(``)`**currently only supported for matrices of**`N``<``=``3`

: returns the inverse of the matrix if one exists.`.``invert``(``)`**currently unimplemented**

## Limitations

Individual component access isn't implemented for vectors and most likely will
not be as simple as a public field access when it is. For now, manually
destructure the vector or use

and `Index`

:`IndexMut`

`let` a `=` `Vector1``::``<``u32``>``::`from`(``[` `5` `]``)``;`
`assert_eq!``(`a`[``0``]``,` `5``)``;`
`let` `mut` b `=` `Vector2``::``<``u32``>``::`from`(``[` `1``,` `2` `]``)``;`
b`[``1``]` `+``=` `3``;`
`assert_eq!``(`b`[``1``]``,` `5``)``;`

Truncation must be performed by manually destructuring as well, but this is due to a limitation of the current compiler.

## Contributions

Please feel free to submit pull requests of any nature.

## Future work

There is a lot of work that needs to be done on aljabar before it can be considered stable or non-experimental.

- Implement

.`Matrix`invert`::` - Add optional Serde support.
- Add and implement rotational and angular data structures.
- Convert

ops to SIMD implementations.`Vector` - Add more tests and get code coverage to 100%.
- Implement better methods for accessing components of Vectors.
- Add

type.`Point` - Implement faster matrix multiplication algorithms.
- Add procedural macro to create matrices of any width and height combination

#### Dependencies

~762KB

~17K SLoC