or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.mdlinear-algebra.mdstatistical-distributions.md
tile.json

linear-algebra.mddocs/

Linear Algebra Operations

Core vector and matrix operations including creation, manipulation, arithmetic operations, and format conversions. The library provides both dense and sparse implementations with automatic optimization for storage efficiency and computational performance.

Capabilities

Vector Creation

Factory methods for creating vectors in dense and sparse formats with various initialization patterns.

import java.lang.{Double => JavaDouble, Integer => JavaInteger, Iterable => JavaIterable}

object Vectors {
  @varargs
  def dense(firstValue: Double, otherValues: Double*): Vector
  def dense(values: Array[Double]): Vector
  def sparse(size: Int, indices: Array[Int], values: Array[Double]): Vector
  def sparse(size: Int, elements: Seq[(Int, Double)]): Vector
  def sparse(size: Int, elements: JavaIterable[(JavaInteger, JavaDouble)]): Vector
  def zeros(size: Int): Vector
  def norm(vector: Vector, p: Double): Double
  def sqdist(v1: Vector, v2: Vector): Double
}

Usage examples:

import org.apache.spark.ml.linalg._

// Dense vector creation
val dense1 = Vectors.dense(1.0, 2.0, 3.0, 4.0)
val dense2 = Vectors.dense(Array(1.0, 2.0, 3.0, 4.0))

// Sparse vector creation
val sparse1 = Vectors.sparse(4, Array(0, 2), Array(1.0, 3.0))
val sparse2 = Vectors.sparse(4, Seq((0, 1.0), (2, 3.0)))

// Zero vector
val zeros = Vectors.zeros(4)

Vector Operations

Mathematical operations on vectors including norms, distances, and element access.

// Vector trait methods
trait Vector {
  def size: Int
  def toArray: Array[Double]
  def apply(i: Int): Double
  def copy: Vector
  def foreachActive(f: (Int, Double) => Unit): Unit
  def numActives: Int
  def numNonzeros: Int
  def toSparse: SparseVector
  def toDense: DenseVector
  def compressed: Vector
  def argmax: Int
  def dot(v: Vector): Double
}

// Static utility methods
object Vectors {
  def norm(vector: Vector, p: Double): Double
  def sqdist(v1: Vector, v2: Vector): Double
}

Usage examples:

val v1 = Vectors.dense(1.0, 2.0, 3.0)
val v2 = Vectors.sparse(3, Array(0, 2), Array(1.0, 3.0))

// Element access
val element = v1(1) // Returns 2.0

// Vector properties
val size = v1.size
val nnz = v1.numNonzeros
val actives = v1.numActives

// Vector operations
val l2Norm = Vectors.norm(v1, 2.0)
val l1Norm = Vectors.norm(v1, 1.0)
val distance = Vectors.sqdist(v1, v2)
val dotProduct = v1.dot(v2)

// Format conversions
val dense = v2.toDense
val sparse = v1.toSparse
val compressed = v1.compressed

// Find maximum element index
val maxIdx = v1.argmax

Matrix Creation

Factory methods for creating matrices in dense and sparse formats with support for various initialization patterns and random generation.

import java.util.Random

object Matrices {
  def dense(numRows: Int, numCols: Int, values: Array[Double]): Matrix
  def sparse(numRows: Int, numCols: Int, colPtrs: Array[Int], rowIndices: Array[Int], values: Array[Double]): Matrix
  def zeros(numRows: Int, numCols: Int): Matrix
  def ones(numRows: Int, numCols: Int): Matrix
  def eye(n: Int): Matrix
  def speye(n: Int): Matrix
  def rand(numRows: Int, numCols: Int, rng: Random): Matrix
  def sprand(numRows: Int, numCols: Int, density: Double, rng: Random): Matrix
  def randn(numRows: Int, numCols: Int, rng: Random): Matrix
  def sprandn(numRows: Int, numCols: Int, density: Double, rng: Random): Matrix
  def diag(vector: Vector): Matrix
  def horzcat(matrices: Array[Matrix]): Matrix
  def vertcat(matrices: Array[Matrix]): Matrix
}

object DenseMatrix {
  def zeros(numRows: Int, numCols: Int): DenseMatrix
  def ones(numRows: Int, numCols: Int): DenseMatrix
  def eye(n: Int): DenseMatrix
  def rand(numRows: Int, numCols: Int, rng: Random): DenseMatrix
  def randn(numRows: Int, numCols: Int, rng: Random): DenseMatrix
  def diag(vector: Vector): DenseMatrix
}

object SparseMatrix {
  def fromCOO(numRows: Int, numCols: Int, entries: Iterable[(Int, Int, Double)]): SparseMatrix
  def speye(n: Int): SparseMatrix
  def sprand(numRows: Int, numCols: Int, density: Double, rng: Random): SparseMatrix
  def sprandn(numRows: Int, numCols: Int, density: Double, rng: Random): SparseMatrix
  def spdiag(vector: Vector): SparseMatrix
}

Usage examples:

import org.apache.spark.ml.linalg._
import java.util.Random

// Dense matrix creation
val dense = Matrices.dense(2, 3, Array(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
val zeros = Matrices.zeros(3, 3)
val ones = Matrices.ones(2, 2)
val identity = Matrices.eye(3)

// Sparse matrix creation  
val sparse = Matrices.sparse(3, 3, Array(0, 1, 2, 3), Array(0, 1, 2), Array(1.0, 2.0, 3.0))
val sparseIdentity = Matrices.speye(3)

// Random matrices
val rng = new Random(42)
val randDense = Matrices.rand(3, 3, rng)
val randSparse = Matrices.sprand(3, 3, 0.3, rng)

// Diagonal matrices
val diagVec = Vectors.dense(1.0, 2.0, 3.0)
val diagMatrix = Matrices.diag(diagVec)

// Matrix concatenation
val m1 = Matrices.ones(2, 2)
val m2 = Matrices.zeros(2, 2)
val horizontal = Matrices.horzcat(Array(m1, m2))
val vertical = Matrices.vertcat(Array(m1, m2))

// COO format creation
val entries = Seq((0, 0, 1.0), (1, 1, 2.0), (2, 2, 3.0))
val coo = SparseMatrix.fromCOO(3, 3, entries)

Matrix Operations

Operations on matrices including element access, arithmetic operations, transposition, and format conversions.

trait Matrix {
  def numRows: Int
  def numCols: Int
  val isTransposed: Boolean
  def toArray: Array[Double]
  def colIter: Iterator[Vector]
  def rowIter: Iterator[Vector]
  def apply(i: Int, j: Int): Double
  def copy: Matrix
  def transpose: Matrix
  def multiply(y: DenseMatrix): DenseMatrix
  def multiply(y: DenseVector): DenseVector
  def multiply(y: Vector): DenseVector
  def toString(maxLines: Int, maxLineWidth: Int): String
  def foreachActive(f: (Int, Int, Double) => Unit): Unit
  def numNonzeros: Int
  def numActives: Int
  def toSparseColMajor: SparseMatrix
  def toSparseRowMajor: SparseMatrix
  def toSparse: SparseMatrix
  def toDense: DenseMatrix
  def toDenseRowMajor: DenseMatrix
  def toDenseColMajor: DenseMatrix
  def compressedColMajor: Matrix
  def compressedRowMajor: Matrix
  def compressed: Matrix
}

Usage examples:

val matrix = Matrices.dense(2, 3, Array(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
val vector = Vectors.dense(1.0, 2.0, 3.0)

// Matrix properties
val rows = matrix.numRows
val cols = matrix.numCols
val isTransposed = matrix.isTransposed

// Element access
val element = matrix(0, 1)

// Matrix operations
val transposed = matrix.transpose
val copy = matrix.copy

// Matrix-vector multiplication
val result1 = matrix.multiply(vector)

// Matrix-matrix multiplication
val other = DenseMatrix.ones(3, 2)
val result2 = matrix.multiply(other)

// Format conversions
val sparse = matrix.toSparse
val denseColMajor = matrix.toDenseColMajor
val compressed = matrix.compressed

// Iteration over columns/rows
matrix.colIter.foreach { col =>
  println(s"Column: ${col.toArray.mkString(", ")}")
}

// Apply function to active elements
matrix.foreachActive { (i, j, value) =>
  println(s"matrix($i, $j) = $value")
}

// Statistics
val nnz = matrix.numNonzeros
val actives = matrix.numActives

Vector Types

Dense and sparse vector implementations with different storage characteristics.

class DenseVector(val values: Array[Double]) extends Vector {
  // Inherits all Vector methods
  // Direct array access for maximum performance
}

class SparseVector(
  override val size: Int,
  val indices: Array[Int],
  val values: Array[Double]
) extends Vector {
  // Inherits all Vector methods
  // Compressed storage for sparse data
}

Matrix Types

Dense and sparse matrix implementations supporting different storage layouts.

class DenseMatrix(
  val numRows: Int,
  val numCols: Int,
  val values: Array[Double],
  override val isTransposed: Boolean = false
) extends Matrix {
  // Convenience constructor
  def this(numRows: Int, numCols: Int, values: Array[Double]) = 
    this(numRows, numCols, values, false)
}

class SparseMatrix(
  val numRows: Int,
  val numCols: Int,
  val colPtrs: Array[Int],
  val rowIndices: Array[Int],
  val values: Array[Double],
  override val isTransposed: Boolean = false
) extends Matrix {
  // Convenience constructor
  def this(numRows: Int, numCols: Int, colPtrs: Array[Int], 
           rowIndices: Array[Int], values: Array[Double]) = 
    this(numRows, numCols, colPtrs, rowIndices, values, false)
}

BLAS Operations

Basic Linear Algebra Subprograms providing optimized implementations of fundamental linear algebra operations.

object BLAS {
  // Level 1: Vector-Vector operations
  def axpy(a: Double, x: Vector, y: Vector): Unit
  def dot(x: Vector, y: Vector): Double
  def copy(x: Vector, y: Vector): Unit
  def scal(a: Double, x: Vector): Unit
  
  // Level 2: Matrix-Vector operations  
  def gemv(alpha: Double, A: Matrix, x: Vector, beta: Double, y: DenseVector): Unit
  def gemv(alpha: Double, A: Matrix, x: Array[Double], beta: Double, y: Array[Double]): Unit
  def spr(alpha: Double, v: Vector, U: DenseVector): Unit
  def spr(alpha: Double, v: Vector, U: Array[Double]): Unit
  def syr(alpha: Double, x: Vector, A: DenseMatrix): Unit
  def dspmv(n: Int, alpha: Double, A: DenseVector, x: DenseVector, beta: Double, y: DenseVector): Unit
  
  // Level 3: Matrix-Matrix operations
  def gemm(alpha: Double, A: Matrix, B: DenseMatrix, beta: Double, C: DenseMatrix): Unit
  def gemm(alpha: Double, A: Matrix, B: DenseMatrix, beta: Double, CValues: Array[Double]): Unit
}

Usage examples:

import org.apache.spark.ml.linalg._

val x = Vectors.dense(1.0, 2.0, 3.0)
val y = Vectors.dense(4.0, 5.0, 6.0).copy.asInstanceOf[DenseVector]

// Level 1 operations
val dotProduct = BLAS.dot(x, y)  // Compute x · y
BLAS.scal(2.0, y)  // Scale y by 2.0: y = 2.0 * y
BLAS.axpy(1.5, x, y)  // Compute y = 1.5 * x + y

// Level 2 operations
val A = Matrices.dense(2, 3, Array(1.0, 2.0, 3.0, 4.0, 5.0, 6.0))
val result = Vectors.zeros(2).asInstanceOf[DenseVector]
BLAS.gemv(1.0, A, x, 0.0, result)  // result = A * x

// Level 3 operations
val B = Matrices.dense(3, 2, Array(1.0, 0.0, 0.0, 1.0, 1.0, 0.0)).asInstanceOf[DenseMatrix]
val C = DenseMatrix.zeros(2, 2)
BLAS.gemm(1.0, A, B, 0.0, C)  // C = A * B

Design Notes

  • Automatic Format Selection: The library automatically chooses between dense and sparse formats based on storage efficiency
  • Lazy Transposition: Matrix transposition is performed lazily without copying data
  • Breeze Integration: Built on top of Breeze for optimized scientific computing operations
  • Memory Efficiency: Sparse formats are used when they provide significant memory savings
  • Thread Safety: All vector and matrix types are immutable and thread-safe for read operations
  • BLAS Optimization: BLAS operations leverage optimized native libraries (OpenBLAS, Intel MKL) when available