Tensorism
A small experimental library for manipulating arrays with multiple indexes. It is meant to be:
* Concise: Specific macros can be used to easily express transformations in a form similar to
the related mathematical expressions.
* Type-safe: Compatibility of dimensions can be checked at compilation time.
Overview
Tensorism is divided into two sibling crates:
* tensorism (this library) contains types and traits.
* tensorism-gen contains macros to
efficiently write formulas.
Examples
- Computing the trace of a matrix:
```rust
use tensorism_gen::make;
use std::iter::Sum;
let mM: Tensor2, StaticDimTag<4>, f64> = …;
let tau = make!(::sum(i $ mM[i, i])); // Or equivalently: make!((i $ mM[i, i]).sum())
```
$$\tau \leftarrow \sum{i=0}^3 M{i, i}$$
- Multiplying two matrices:
```rust
use tensorism_gen::make;
use std::iter::Sum;
let mA: Tensor2, StaticDimTag<4>, Complex64> = …;
let mB: Tensor2, StaticDimTag<5>, Complex64> = …;
let mC = make!(i k $ ::sum(j $ mA[i, j] * mB[j, k]));
```
$$\forall i \in 0 .. 7,\quad \forall k \in 0 .. 5,\quad C{i, k} \leftarrow \sum{0 \leq j < 4} A{i, j} \cdot B{j, k}$$
- Finding the maximum values (here almong instants) according to given "axes":
```rust
use tensorismgen::make;
use datetime::Instant;
fn maximumof(it: impl Iterator
- ) -> Instant { … }
let tD: Tensor3, StaticDimTag<25>, StaticDimTag<3>, Instant> = …;
let mX = make!(i j $ maximumof(k $ tD[i, j, k])); // : Tensor2, StaticDimTag<25>, Instant>
let mY = make!(k i $ maximumof(j $ tD[i, j, k])); // : Tensor2, StaticDimTag<10>, Instant>
let v = make!(j $ maximumof(i k $ tD[i, j, k])); // : Tensor1, Instant>
let d = make!(maximumof(i j k $ tD[i, j, k])); // : Instant
```
$$\forall i \in 0 .. 10,\quad \forall j \in 0 .. 25,\quad X{i, j} \leftarrow \max{0 \leq k < 3} D_{i, j, k}$$
$$\forall k \in 0 .. 3,\quad \forall i \in 0 .. 10,\quad Y{k, i} \leftarrow \max{0 \leq j < 25} D_{i, j, k}$$
$$\forall j \in 0 .. 25,\quad vj \leftarrow \underset{0 \leq k < 3}{\max{0 \leq i < 10}} D_{i, j, k}$$
$$d \leftarrow \underset{0 \leq k < 3}{\underset{0 \leq j < 25}{\max{0 \leq i < 10}}} D{i, j, k}$$
- Computing intersections:
```rust
use tensorismgen::make;
use std::string::String;
use std::collections::HashSet;
fn intersectionof<'a>(it: impl Iterator
- >) -> HashSet { … }
let mA: Tensor2, StaticDimTag<3>, HashSet> = …;
let u = make!(i $ intersectionof(j $ &mA[i, j])); // : Tensor1, HashSet>
let v = make!(j $ intersectionof(i $ &mA[i, j])); // : Tensor1, HashSet>
```
$$\forall i \in 0 .. 4,\quad uj \leftarrow \bigcap{0 \leq j < 3} A_{i, j}$$
$$\forall j \in 0 .. 3,\quad vj \leftarrow \bigcap{0 \leq i < 4} A_{i, j}$$
- Computing logical conjunctions and disjunctions:
```rust
use tensorism_gen::make;
fn forall(it: impl Iterator
- ) -> bool { … }
fn exists(it: impl Iterator
- ) -> bool { … }
let q: Tensor3, StaticDimTag<9>, StaticDimTag<7>, bool> = …;
let p = make!(k $ forall(i $ exists(j $ q[i, j, k])));
```
$$\forall k \in 0 .. 7,\quad pk \leftarrow \Big( \forall i \in 0 .. 3, \ \exists j \in 0 .. 9, \ q{i, j, k} \Big)$$
- Any combination:
```rust
use tensorism_gen::make;
let q: Tensor3, StaticDimTag<9>, StaticDimTag<7>, bool> = …;
let mA: Tensor2, StaticDimTag<13>, f64> = …;
let mB: Tensor2, StaticDimTag<13>, f64> = …;
let mLambda: Tensor2, StaticDimTag<13>, f64> = …;
fn product(it: impl Iterator
- ) -> f64 { … }
let mZ = make!(i k $ if exists(j $ q[i, j, k] && 0f64 <= mA[i, j]) {
::sum(l $ mLambda[k, l] * sin(2 * PI * mA[i, l]))
} else {
product(m $ mA[i, m] + mB[k, m])
});
```
$$\forall i \in 0 .. 3,\quad \forall k \in 0 .. 7,\quad Z{i, k} \leftarrow \begin{cases}
\sum{0 \leq l < 13} \Lambda{k, l} \cdot \sin\left(2 \cdot \pi \cdot A{i, l} \right) & \mathrm{if} & \exists j \in 0 .. 9, \ q{i, j, k} \wedge 0 \leq A{i, j}\
\prod{0 \leq m < 13} (A{i, m} + B_{k, m}) & \mathrm{else}
\end{cases}$$