## SLAS *Static Linear Algebra System* [![GitHub Workflow Status](https://img.shields.io/github/workflow/status/unic0rn9k/slas/Tests?label=tests&logo=github&style=flat-square)](https://github.com/unic0rn9k/slas/actions/workflows/rust.yml) [![Crates.io](https://img.shields.io/crates/v/slas?logo=rust&style=flat-square)](https://crates.io/crates/slas) [![Docs](https://img.shields.io/docsrs/slas/latest?logo=rust&style=flat-square)](https://docs.rs/slas/latest/slas/) [![Donate on paypal](https://img.shields.io/badge/paypal-donate-1?style=flat-square&logo=paypal&color=blue)](https://www.paypal.com/paypalme/unic0rn9k/5usd)

Provides statically allocated vector, matrix and tensor types, for interfacing with blas/blis, in a performant manor, using copy-on-write (aka cow) behavior.

Example

rust use slas::prelude::*; let a = moo![f32: 1, 2, 3.2]; let b = moo![f32: 3, 0.4, 5]; println!("Dot product of {:?} and {:?} is {:?}", a, b, a.dot(&b)); More example code here.

What is a COW?

The copy-on-write functionality is inspired by std::borrow::cow. 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), but I'm planing on making ways around this in the future.

In code...

```rust let source: Vec = vec![1., 2., 3.]; let mut v = moo![_ source.as_slice()];

// Here we mutate v, // so the content of source will be copied into v before the mutation occours. v[0] = 0.;

asserteq!(*v, [0., 2., 3.]); asserteq!(source, vec![1., 2., 3.]); ```

The borrow checker won't allow mutating source after v is created, because assignment to borrowed values is not allowed. This can be a problem in some situations.

```rust let mut source: Vec = vec![1., 2., 3.]; let mut v = unsafe { StaticCowVec::::fromptr(source.asptr()) };

// Here we can mutate source, because v was created from a raw pointer. source[1] = 3.; v[0] = 0.; source[2] = 4.;

asserteq!(*v, [0., 3., 3.]); asserteq!(source, vec![1., 3., 4.]); `` In the example above, you can seevchanged value the first timesourcewas mutated, but not the second time. This is becausevwas copied when it was mutated at the line after the first mutation ofsource`.

Matricies, tensors and other mathematical types

At the moment the way I want to implement these types, causes a compiler crash, when trying to create 2 objects with the same shape. For now I'm going to try to create a temporary, and more stable, way of dealing with these variations of static multi dimensional arrays.

As of now there is a Matrix type, but no tensor type on the master branch. The stable matricies are very basic, as I hopefully will be able to replace them with a more generic tensor type soon...

```rust use slas::{prelude::*, matrix::Matrix};

let m: Matrix = [ 1., 2., 3., 4., 5., 6. ].into();

assert!(m[[1, 0]] == 2.);

let k: Matrix = moo![f32: 0..6].into();

println!("Product of {:?} and {:?} is {:?}", m, k, m * k); ```

If you want a look at whats to come in the future, you can go here for some very experimental source code for the project.

Why not just use ndarray (or alike)?

Slas can be faster than ndarray in some specifik use cases, like when having to do a lot of allocations, or when using referenced data in vector operations. Besides slas should always be atleast as fast as ndarray, so it can't hurt.

Statical allocation and the way slas cow behavior works with the borrow checker, also means that you might catch a lot of bugs at compiletime, where ndarray most of the time will let you get away with pretty much anything.

More info...

TODO: before publishing 🎉

TODO: after publish

License: Apache-2.0