backends/default API

Luna-Flow/linear-algebra/backends/default is the reference dense backend. It wraps the concrete @mutable and @immut types in four owned structs and implements the algebra traits for them, so that generic code bounded by those traits runs on real dense data. It also provides three trait-bounded helper functions and a few backend methods (scale, dot, axpy, matvec).

Source: src/backends/default. Why the wrappers exist is explained in the backends/default design.

Import

///|
import {
  "Luna-Flow/linear-algebra/algebra",
  "Luna-Flow/linear-algebra/backends/default",
}

Overview

WrapperWrapsSemantics
DenseVector[T]@mutable.Vector[T]shares the wrapped vector; results of operators are new vectors
DenseMatrix[T]@mutable.Matrix[T]shares the wrapped matrix; results of operators are new matrices
ImmutableDenseVector[T]@immut.Vector[T]value semantics
ImmutableDenseMatrix[T]@immut.Matrix[T]value semantics

All operators return a new wrapper around a new inner value; none mutates its operands. Shape mismatches in operators abort, as in the wrapped types.

Generic helpers

shape_of

shape_of(m) returns (rows, cols) of any MatrixShape value.

pub fn[M : @algebra.MatrixShape] shape_of(M) -> (Int, Int)

transpose

transpose(m) returns the transpose of any TransposeMatrix value, of the same type.

pub fn[M : @algebra.TransposeMatrix] transpose(M) -> M

matmul

matmul(a, b) returns a * b for any MatMulMatrix type.

pub fn[M : @algebra.MatMulMatrix] matmul(M, M) -> M

The precondition cols⁡(a)=rows⁡(b)\operatorname{cols}(a) = \operatorname{rows}(b) and the failure behaviour are those of the type’s *; for the dense wrappers a mismatch aborts.

///|
test "generic helpers on dense wrappers" {
  let a = @default.DenseMatrix::from_2d_array([[1, 2, 3], [4, 5, 6]])
  debug_inspect(@default.shape_of(a), content="(2, 3)")
  let at = @default.transpose(a)
  debug_inspect(@default.shape_of(at), content="(3, 2)")
  inspect(@default.matmul(a, at).inner(), content="|14, 32|\n|32, 77|")
}

DenseVector

DenseVector

DenseVector[T] is the mutable dense vector wrapper.

pub struct DenseVector[T] {
  inner : @mutable.Vector[T]
}

The field is readable from other packages. Implemented traits: Add, Neg, Sub and Mul (element-wise) under the element constraints of the methods below, @algebra.VectorShape for all T, @algebra.AdditiveVector when T : Add + Neg, and @algebra.VecMulVector when T : Add + Neg + Mul.

DenseVector::from_array

DenseVector::from_array(xs) wraps a new @mutable.Vector built from xs.

pub fn[T] DenseVector::from_array(Array[T]) -> Self[T]

The array is not copied: the wrapper and xs share storage, as with @mutable.Vector::from_array.

DenseVector::from_backend

DenseVector::from_backend(v) wraps an existing @mutable.Vector without copying.

pub fn[T] DenseVector::from_backend(@mutable.Vector[T]) -> Self[T]

DenseVector::make

DenseVector::make(n, x) builds a vector of length n filled with x.

pub fn[T] DenseVector::make(Int, T) -> Self[T]

DenseVector::inner

DenseVector::inner(v) returns the wrapped @mutable.Vector; writes to it are visible through the wrapper.

pub fn[T] DenseVector::inner(Self[T]) -> @mutable.Vector[T]

DenseVector::length

DenseVector::length(v) returns the number of elements.

pub fn[T] DenseVector::length(Self[T]) -> Int

DenseVector::at

DenseVector::at(v, i) returns element i; it backs v[i].

#alias("_[_]")
pub fn[T] DenseVector::at(Self[T], Int) -> T

An index outside 0..<length aborts.

DenseVector::add, DenseVector::sub, DenseVector::neg

These are the promoted operator methods behind u + v, u - v and -v.

pub fn[T : Add] DenseVector::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] DenseVector::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] DenseVector::neg(Self[T]) -> Self[T]

Operands of different lengths abort. Subtraction is computed as u+(−v)u + (-v).

DenseVector::mul

DenseVector::mul(u, v) is the element-wise (Hadamard) product behind u * v.

pub fn[T : Mul] DenseVector::mul(Self[T], Self[T]) -> Self[T]

DenseVector::scale

DenseVector::scale(v, a) returns (vi⋅a)i(v_i \cdot a)_i, multiplying each element on the right by the scalar.

pub fn[T : Mul] DenseVector::scale(Self[T], T) -> Self[T]

DenseVector::dot

DenseVector::dot(u, v) returns ∑iuivi\sum_i u_i v_i, summed left to right from Zero::zero().

pub fn[T : @luna-generic.AddMonoid + Mul] DenseVector::dot(Self[T], Self[T]) -> T

Vectors of different lengths abort.

DenseVector::axpy

DenseVector::axpy(x, a, y) returns xa+yx a + y, the BLAS axpy combination with self as xx.

pub fn[T : Add + Mul] DenseVector::axpy(Self[T], T, Self[T]) -> Self[T]

The result is a new vector; y is not updated in place.

///|
test "DenseVector backend methods" {
  let x = @default.DenseVector::from_array([1.0, 2.0, 3.0])
  let y = @default.DenseVector::make(3, 1.0)
  inspect(x.dot(y), content="6")
  inspect(x.axpy(2.0, y).inner(), content="|3, 5, 7|")
  inspect((x * x - y).inner(), content="|0, 3, 8|")
  inspect(x[2], content="3")
  inspect(@algebra.VectorShape::length(x), content="3")
}

DenseMatrix

DenseMatrix

DenseMatrix[T] is the mutable dense matrix wrapper.

pub struct DenseMatrix[T] {
  inner : @mutable.Matrix[T]
}

Implemented traits: Add, Neg, Sub, Mul (matrix product), @algebra.MatrixShape and @algebra.TransposeMatrix for all T, @algebra.AdditiveMatrix when T : Add + Neg, and @algebra.MatMulMatrix when T : Add + Neg + AddMonoid + Mul.

DenseMatrix::from_2d_array

DenseMatrix::from_2d_array(rows) builds a matrix from nested row arrays.

pub fn[T] DenseMatrix::from_2d_array(Array[Array[T]]) -> Self[T]

Ragged input aborts; [] gives a 0×00 \times 0 matrix.

DenseMatrix::from_backend

DenseMatrix::from_backend(m) wraps an existing @mutable.Matrix without copying.

pub fn[T] DenseMatrix::from_backend(@mutable.Matrix[T]) -> Self[T]

DenseMatrix::new

DenseMatrix::new(r, c, x) builds an r×cr \times c matrix filled with x.

pub fn[T] DenseMatrix::new(Int, Int, T) -> Self[T]

Negative dimensions abort.

DenseMatrix::inner

DenseMatrix::inner(m) returns the wrapped @mutable.Matrix, which gives access to the full @mutable API (views, decompositions, checked methods).

pub fn[T] DenseMatrix::inner(Self[T]) -> @mutable.Matrix[T]

DenseMatrix::row, DenseMatrix::col

row and col return the number of rows and columns.

pub fn[T] DenseMatrix::row(Self[T]) -> Int
pub fn[T] DenseMatrix::col(Self[T]) -> Int

DenseMatrix::shape

DenseMatrix::shape(m) returns (rows, cols); it is the promoted @algebra.MatrixShape::shape.

pub fn[T] DenseMatrix::shape(Self[T]) -> (Int, Int)

DenseMatrix::transpose

DenseMatrix::transpose(m) returns a materialized transpose; it is the promoted @algebra.TransposeMatrix::transpose.

pub fn[T] DenseMatrix::transpose(Self[T]) -> Self[T]

DenseMatrix::add, DenseMatrix::sub, DenseMatrix::neg

Entry-wise +, - and unary -.

pub fn[T : Add] DenseMatrix::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] DenseMatrix::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] DenseMatrix::neg(Self[T]) -> Self[T]

Operands of different shapes abort.

DenseMatrix::mul

DenseMatrix::mul(a, b) is the matrix product behind a * b.

pub fn[T : @luna-generic.AddMonoid + Mul] DenseMatrix::mul(Self[T], Self[T]) -> Self[T]

cols⁡(a)≠rows⁡(b)\operatorname{cols}(a) \ne \operatorname{rows}(b) aborts with Matrix::mul: dimension mismatch. Cost: rcnrcn multiply-adds.

DenseMatrix::matvec

DenseMatrix::matvec(a, x) returns the matrix-vector product AxA x as a new DenseVector.

pub fn[T : @luna-generic.AddMonoid + Mul] DenseMatrix::matvec(Self[T], DenseVector[T]) -> DenseVector[T]

A length mismatch aborts; use a.inner().mul_vec(x.inner()) for a checked version.

///|
test "DenseMatrix operations" {
  let a = @default.DenseMatrix::from_2d_array([[2, 0], [1, 3]])
  let x = @default.DenseVector::from_array([1, 1])
  inspect(a.matvec(x).inner(), content="|2, 4|")
  inspect((a * a).inner(), content="|4, 0|\n|5, 9|")
  inspect(a.transpose().inner(), content="|2, 1|\n|0, 3|")
  debug_inspect(a.shape(), content="(2, 2)")
  inspect(a.inner().trace().unwrap(), content="5")
}

ImmutableDenseVector

ImmutableDenseVector

ImmutableDenseVector[T] is the immutable dense vector wrapper.

pub struct ImmutableDenseVector[T] {
  inner : @immut.Vector[T]
}

It implements the same traits as DenseVector under the same constraints.

ImmutableDenseVector::from_array

ImmutableDenseVector::from_array(xs) copies xs into a new @immut.Vector.

pub fn[T] ImmutableDenseVector::from_array(Array[T]) -> Self[T]

ImmutableDenseVector::from_backend

ImmutableDenseVector::from_backend(v) wraps an existing @immut.Vector.

pub fn[T] ImmutableDenseVector::from_backend(@immut.Vector[T]) -> Self[T]

ImmutableDenseVector::make

ImmutableDenseVector::make(n, x) builds a vector of length n filled with x.

pub fn[T] ImmutableDenseVector::make(Int, T) -> Self[T]

ImmutableDenseVector::inner

ImmutableDenseVector::inner(v) returns the wrapped @immut.Vector.

pub fn[T] ImmutableDenseVector::inner(Self[T]) -> @immut.Vector[T]

ImmutableDenseVector::length

ImmutableDenseVector::length(v) returns the number of elements.

pub fn[T] ImmutableDenseVector::length(Self[T]) -> Int

ImmutableDenseVector::at

ImmutableDenseVector::at(v, i) returns element i; it backs v[i].

#alias("_[_]")
pub fn[T] ImmutableDenseVector::at(Self[T], Int) -> T

ImmutableDenseVector::add, ImmutableDenseVector::sub, ImmutableDenseVector::neg, ImmutableDenseVector::mul

Element-wise +, -, unary - and Hadamard *.

pub fn[T : Add] ImmutableDenseVector::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] ImmutableDenseVector::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] ImmutableDenseVector::neg(Self[T]) -> Self[T]
pub fn[T : Mul] ImmutableDenseVector::mul(Self[T], Self[T]) -> Self[T]

ImmutableDenseVector::scale

ImmutableDenseVector::scale(v, a) returns (vi⋅a)i(v_i \cdot a)_i.

pub fn[T : Mul] ImmutableDenseVector::scale(Self[T], T) -> Self[T]

ImmutableDenseVector::dot

ImmutableDenseVector::dot(u, v) returns ∑iuivi\sum_i u_i v_i.

pub fn[T : @luna-generic.Zero + Add + Mul] ImmutableDenseVector::dot(Self[T], Self[T]) -> T

Vectors of different lengths abort.

ImmutableDenseVector::axpy

ImmutableDenseVector::axpy(x, a, y) returns xa+yx a + y.

pub fn[T : Add + Mul] ImmutableDenseVector::axpy(Self[T], T, Self[T]) -> Self[T]

ImmutableDenseMatrix

ImmutableDenseMatrix

ImmutableDenseMatrix[T] is the immutable dense matrix wrapper.

pub struct ImmutableDenseMatrix[T] {
  inner : @immut.Matrix[T]
}

It implements the same traits as DenseMatrix; @algebra.MatMulMatrix needs T : Add + Neg + Zero + Mul.

ImmutableDenseMatrix::from_2d_array

ImmutableDenseMatrix::from_2d_array(rows) builds a matrix from nested rows; ragged input aborts.

pub fn[T] ImmutableDenseMatrix::from_2d_array(Array[Array[T]]) -> Self[T]

ImmutableDenseMatrix::from_backend

ImmutableDenseMatrix::from_backend(m) wraps an existing @immut.Matrix.

pub fn[T] ImmutableDenseMatrix::from_backend(@immut.Matrix[T]) -> Self[T]

ImmutableDenseMatrix::new

ImmutableDenseMatrix::new(r, c, x) builds an r×cr \times c matrix filled with x.

pub fn[T] ImmutableDenseMatrix::new(Int, Int, T) -> Self[T]

ImmutableDenseMatrix::inner

ImmutableDenseMatrix::inner(m) returns the wrapped @immut.Matrix.

pub fn[T] ImmutableDenseMatrix::inner(Self[T]) -> @immut.Matrix[T]

ImmutableDenseMatrix::row, ImmutableDenseMatrix::col, ImmutableDenseMatrix::shape

Row count, column count and (rows, cols); shape is the promoted @algebra.MatrixShape::shape.

pub fn[T] ImmutableDenseMatrix::row(Self[T]) -> Int
pub fn[T] ImmutableDenseMatrix::col(Self[T]) -> Int
pub fn[T] ImmutableDenseMatrix::shape(Self[T]) -> (Int, Int)

ImmutableDenseMatrix::transpose

ImmutableDenseMatrix::transpose(m) returns the transpose; it is the promoted @algebra.TransposeMatrix::transpose.

pub fn[T] ImmutableDenseMatrix::transpose(Self[T]) -> Self[T]

ImmutableDenseMatrix::add, ImmutableDenseMatrix::sub, ImmutableDenseMatrix::neg, ImmutableDenseMatrix::mul

Entry-wise +, -, unary -, and the matrix product.

pub fn[T : Add] ImmutableDenseMatrix::add(Self[T], Self[T]) -> Self[T]
pub fn[T : Add + Neg] ImmutableDenseMatrix::sub(Self[T], Self[T]) -> Self[T]
pub fn[T : Neg] ImmutableDenseMatrix::neg(Self[T]) -> Self[T]
pub fn[T : Add + @luna-generic.Zero + Mul] ImmutableDenseMatrix::mul(Self[T], Self[T]) -> Self[T]

Shape mismatches abort.

ImmutableDenseMatrix::matvec

ImmutableDenseMatrix::matvec(a, x) returns AxA x as a new ImmutableDenseVector; a length mismatch aborts.

pub fn[T : Add + @luna-generic.Zero + Mul] ImmutableDenseMatrix::matvec(Self[T], ImmutableDenseVector[T]) -> ImmutableDenseVector[T]
///|
test "immutable wrappers" {
  let a = @default.ImmutableDenseMatrix::from_2d_array([[1, 2], [3, 4]])
  let x = @default.ImmutableDenseVector::from_array([1, -1])
  inspect(a.matvec(x).inner(), content="|-1, -1|")
  inspect((a - a.transpose()).inner(), content="|0, -1|\n|1, 0|")
  inspect(x.dot(x), content="2")
  inspect(x.scale(3).inner(), content="|3, -3|")
}