*Static Linear Algebra System*
[![Crates.io](https://img.shields.io/crates/v/slas?logo=rust)](https://crates.io/crates/slas)
[![GitHub Workflow Status](https://img.shields.io/github/workflow/status/unic0rn9k/slas/Tests?label=tests&logo=github)](https://github.com/unic0rn9k/slas/actions/workflows/rust.yml)
[![Coverage Status](https://coveralls.io/repos/github/unic0rn9k/slas/badge.svg?branch=master)](https://coveralls.io/github/unic0rn9k/slas?branch=master)
[![Docs](https://img.shields.io/docsrs/slas/latest?logo=rust)](https://docs.rs/slas/latest/slas/)
[![Donate on paypal](https://img.shields.io/badge/paypal-donate-1?logo=paypal&color=blue)](https://www.paypal.com/paypalme/unic0rn9k/5usd)
A linear algebra system with a focus on performance, static allocation, statically shaped data and copy-on-write (aka cow) behavior.
Safe and fast bindings for blas/blis are also provided out of the box.
### The mission
The goal of slas is to provide the best perfomance given the most amount of information that can be known at compile time.
This mainly includes shapes and sizes of algebraic objects,
target architecture and available hardware features/devices.
Please keep in mind that slas specializes in cases where binaries are compiled and executed on the same system and thus is primarily intended for native compilation.
**NOTE:** Slas might still be very broken when **not** using native compilation.
Specialization in hardware and usecases is attempted to be done with the [modular backend system](https://docs.rs/slas/latest/slas/backends/index.html),
which will support custom allocators in the future.
[What is BLAS?](http://www.netlib.org/blas/)
### Example
A `StaticCowVec` can be created both with the `moo` and the `cow_vec` macro.
They have the exact same syntax, but the cow_vec macro is a great choice for the serious programmer.
Better documentation for the moo macro can be found [here](https://docs.rs/slas/latest/slas/macro.moo.html).
```rust
use slas::prelude::*;
use slas::cow_vec;
let a = moo![f32: 1, 2, 3.2];
let b = cow_vec![f32: 3, 0.4, 5];
println!("Dot product of {a:?} and {b:?} is {:?}", a.dot(&b));
println!("{a:?} + {b:?} = {:?}", a.add(&b));
```
By default slas tries to select a backend for you, you can also choose a static backend yourself.
([More about what exactly a backend is and how to configure it.](https://docs.rs/slas/latest/slas/backends/index.html))
```rust
use slas::prelude::*;
let a = moo![on slas_backend::Rust:f32: 1, 2, 3.2];
// This will only use rust code for all operations on a
```
```rust
use slas::prelude::*;
let a = moo![on slas_backend::Blas:f32: 1, 2, 3.2];
// This will always use blas for all operations on a
```
By default slas will choose the backend that is assumed to be the fastest, given options set in environment during build
([more about that here](https://github.com/unic0rn9k/slas#Enviroments-variables)).
The `StaticCowVec` dereferences to `StaticVecUnion`, which in turn dereferences to `[T; LEN]`,
so any method implemented for `[T;LEN]` can also be called on `StaticCowVec` and `StaticVecUnion`.
[More example code here.](https://github.com/unic0rn9k/slas/blob/master/tests/src/main.rs)
### What is a cow and when is it useful?
The copy-on-write functionality is inspired by [std::borrow::cow](https://doc.rust-lang.org/std/borrow/enum.Cow.html).
The idea is simply that allocations (and time) can be saved, by figuring out when to copy at runtime instead of at compiletime.
This can be memory inefficient at times (as an enum takes the size of its largest field + tag size), which is why you can optionally use `StaticVecUnion`s and `StaticVec`s instead.
You can call `moo`, `moo_ref` and `mut_moo_ref` on any type that implements `StaticVec` to cast it to a appropriate type for it's use-case, with zero overhead.
**moo_ref** returns a `StaticVecRef`, which is just a type alias for a reference to a `StaticVecUnion`.
This is most efficient when you know you don't need mutable access or ownership of a vector.
**mut_moo_ref** returns a `MutStaticVecRef`.
This is a lot like `moo_ref`, but is useful when you want to mutate your data in place (fx if you wan't to normalize a vector).
You should only use this if you want mutable access to a vector WITH side effects.
**moo** returns a `StaticCowVec` that references `self`. This is useful if you don't know if you need mutable access to you vector and you don't want side effects.
If you want to copy data into a `StaticCowVec` then `StaticCowVec::from` is what you need.
**moo_owned** will just return a `StaticVecUnion`. This is useful when you really just want a `[T; LEN]`,
but you need methods only implemented for a `StaticVecUnion`.
### Example of cow behavior
```rust
use slas::prelude::*;
let source: Vec