Skip to content
/ slut Public

Static Linear Untiful Tensors. Library for Vectors and Matrices with Physical Dimensions. Basically `uom` but in a vector space.

License

Notifications You must be signed in to change notification settings

PKD667/slut

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

39 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Static Linear Unitfull Tensors

This is a small lib I made for my thermodynamics simulation project. I was fed up with implementing vectors in uom. It's very bug prone, experimental but does the job quite well. Inspired by Terry Tao's post and yuouom.

It's very useful for a lot of things like physics simulation, linear algebra, and could even be used as a theorem prover for dimensional analysis. Don't forget to include the experimental headers and use cargo nightly.

#![feature(generic_const_exprs)]
#![feature(trivial_bounds)]
#![feature(generic_arg_infer)]

Usage

You can cargo add the library from this repository. You can find all the structures in slut::tensor units in slut::units and all the dimensions in slut::dimension. You can create tensors of any dimension and any unit. You can also perform operations on tensors like addition, subtraction, scaling, dot product, cross product, matrix multiplication, etc.

// Tensor of lengths
let mass = (10.0).scalar::<Kilogram>();
let force = Vec2::<f64,Force>::new::<Newton>([1.0, 2.0]);

//let error = mass + force; // error (expected)

let mass = mass + Scalar::<f64,Mass>::from::<Gram>(5.0); // works
println!("{}", mass);
/*
Tensor [1x1x1]: M^1
-- Layer 0 --
( 10.005 )
*/

let acc = force.scale(mass.inv()); // works
println!("{}", acc);
/*
Tensor [1x2x1]: L^1 * T^-2
-- Layer 0 --
( 0.09995002498750624 )
( 0.19990004997501248 )
*/

let time = Scalar::<f64,Time>::new::<Second>([1.0]);
let vel1 = Vec2::<f64,Velocity>::new::<MetersPerSecond>([10.0, 20.0]);

let vel2 = vel1 + acc.scale(time); // works
println!("{:?}", vel2.get::<MetersPerSecond>());
/*
[10.099950024987507, 20.199900049975014]
*/

// try to transpose a tensor
let tensor = Tensor::<c64,Dimensionless, 1,1, 6>::new::<Unitless>([1.0, 2.0, 3.0, 4.0, 5.0, 6.0].complex());
let tensor_transposed = tensor.transpose();
println!("{}", tensor);
println!("{}", tensor_transposed);
/*
Tensor [1x1x6]: Dimensionless
-- Layer 0 --
( 1  2  3  4  5  6 )

Tensor [1x6x1]: Dimensionless
-- Layer 0 --
( 1 )
( 2 )
( 3 )
( 4 )
( 5 )
( 6 )
        */

let length = Vec2::<f64,Length>::new::<Meter>([10.0, 20.0]);

// now try and dot product length and force
let dot_product = dot!(length, force);
println!("{}", dot_product);
/*
Tensor [1x1x1]: L^2 * M^1 * T^-2
-- Layer 0 --
( 50 )
*/

assert_dimension!(dot_product, Energy); // works
//assert_dimension!(dot_product, Force); // error (expected)

let m1 = Matrix::<f64,Length, 2, 3>::new::<Meter>([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
let m2 = Matrix::<f64,Length, 3, 2>::new::<Meter>([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);

let m3 = m1.matmul(m2);
println!("{}", m3);
/*
Tensor [1x2x2]: L^2
-- Layer 0 --
( 22  28 )
( 49  64 )
*/


// test openrators
if (vel1 == vel2) {
        println!("Equal");
} else {
        println!("Not equal");
}

let mass2 = Scalar::<f64,Mass>::from::<Kilogram>(10.0);

if (mass == mass2) {
        println!("Equal");
} else {
        if mass < mass2 {
        println!("Less than");
        } else {
        println!("Greater than");
        }
}
/*
Not equal
Greater than
*/



let inv = Scalar::<f64,dim_inv!(Time)>::from::<unit_inv!(Second)>(1.0);

let mul = Scalar::<f64,dim_div!(Energy,Temperature)>::new::<unit_div!(Joule, Kelvin)>([1.0]);

assert_dimension!(mul, Entropy); // works
assert_dimension!(inv, Frequency); // works

println!("{}", inv);
println!("{}", mul);

/*
Tensor [1x1x1]: T^-1
-- Layer 0 --
( 1 )

Tensor [1x1x1]: L^2 * M^1 * T^-2 * Θ^-1
-- Layer 0 --
( 1 )
*/

// test dot product
let a = Vec2::<f64,Length>::new::<Meter>([1.0, 2.0]);
let b = Vec2::<f64,Length>::new::<Meter>([3.0, 4.0]);
let c = dot!(a, b);
println!("{}", c);
/*
        Tensor [1x1x1]: L^2
        -- Layer 0 --
        ( 11 )
*/


// invert
let d = c.inv();
println!("{}", d);

Linear algebra

I also implemented some physics/linald features I use for prototyping quantum sims and other stuff. You can use the cvec! macro to create complex vectors and matrices. You can also use the ip! macro to calculate the inner product of two vectors (hilbert on complex ones).

let a = cvec!((2,4), (3,5));  // [2+4i, 3+5i]
let a_h = a.conjugate_transpose();

println!("{}", a);
println!("{}", a_h);

/*
Tensor [1x2x1]: Dimensionless
-- Layer 0 --
( 2 + 4i )
( 3 + 5i )

Tensor [1x1x2]: Dimensionless
-- Layer 0 --
( 2 - 4i  3 - 5i )
        */



assert_eq!(a_h.get_at(0,0,0).raw(), c64::new(2.0, -4.0));
assert_eq!(a_h.get_at(0,0,1).raw(), c64::new(3.0, -5.0));

let a = cvec!((2,4), (3,5));
let b = cvec!((1,2), (3,4));

println!("a:\n{}", a);
println!("b:\n{}", b);
println!("a†:\n{}", a.conjugate_transpose());
println!("a† × b:\n{}", a.conjugate_transpose().matmul(b));
/*
a:
Tensor [1x2x1]: Dimensionless
-- Layer 0 --
( 2 + 4i )
( 3 + 5i )

b:
Tensor [1x2x1]: Dimensionless
-- Layer 0 --
( 1 + 2i )
( 3 + 4i )

a†:
Tensor [1x1x2]: Dimensionless
-- Layer 0 --
( 2 - 4i  3 - 5i )

a† × b:
Tensor [1x1x1]: Dimensionless
-- Layer 0 --
( 39 - 3i )
        */


let c = ip!(a,b);
println!("c: {}",c);
/*
c: Tensor [1x1x1]: Dimensionless
-- Layer 0 --
( 39 - 3i )
*/

let c_ = dless!((39.0, -3.0).complex());
println!("c_: {}",c_);
/*
c_: Tensor [1x1x1]: Dimensionless
-- Layer 0 --
( 39 - 3i )
*/

// The result should be -17 - 7i
assert_approx_eq!(c, c_);

// Test conjugate symmetry
assert_approx_eq!(ip!(a,b).conjugate(), ip!(b,a));

// Test linearity
let d = cvec!((1,1), (2,2));
let alpha = dless!((2.0, 1.0).complex());

// (a, αb + d) = α(a,b) + (a,d)
assert_approx_eq!(
        ip!(a,(b.scale(alpha) + d)),
        ip!(a,b).scale(alpha) + ip!(a,d)
);

// Test positive definiteness
assert!(ip!(a,a).raw().re() >= 0.0);

Installation

You can find this library at crates.io and github

About

Static Linear Untiful Tensors. Library for Vectors and Matrices with Physical Dimensions. Basically `uom` but in a vector space.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages