# Matrices & Linear Algebra

While it is always possible to use the underlying container classes directly (see Modules for more information on backends), Koma provides a set of top-level convenience functions to make the experience more similar to other scientific environments. All these functions reside in the `koma` namespace and use the underlying object-oriented hierarchy internally.

When working with matrices in Koma you'll almost always want to

```import koma.extensions.*
```

This namespace defines some extension functions which would ordinarily be defined on `Matrix` itself but can't be for performance reasons. Since there are only `Matrix` extension functions defined in `koma.extensions`, it should be safe to star import it without polluting your workspace. If you don't import `koma.extensions` you'll be missing a lot of functionality including basic things like getters and setters.

### Creating Matrices

Koma provides several functions for creating new matrices:

```// x is a 3x3 identity matrix
var x = eye(3)

// x is a 3x3 matrix of zeros
x = zeros(3,3)

// x is a 3x3 with Gaussian random noise, distribution 0,1
x = randn(3,3)

// x is a 3x3 with uniform random noise
x = rand(3,3)

// x is a 4x5 matrix where the ith row and jth column has the value i+j*2
x = fill(4,5) { row, col -> row+col*2.0 }

val someData = arrayOf(doubleArrayOf(1.0,2.0,3.0), doubleArrayOf(4.0,5.0,6.0))
// x is a 2x3 matrix constructed from the data in a java array of arrays
x = create(someData)
```

See here for a complete list of available creators. There is also a DSL for matrix literals:

```// a is a 2x3 matrix filled with the numbers passed in
val a = mat[1,2,3.3 end
4,5,6]
```

### Math Functions

Matrices have useful map functions that return matrices for chaining operations (see here for a complete list).

```// Create a 3x3 identity and then add 0.1 to all elements
val x = eye(3) + 0.1

// Map each element through a function that adds .01
val y = x.map { it + .01 }

// Map each element through a function that adds or subtracts depending on the element index
val z = x.mapIndexed { row, col, ele -> if (row > col) ele + 1 else ele - 1 }

// Are there any elements greater than 1?
val hasGreater = x.any { it > 1 }

// Are all elements greater than 1?
val allGreater = x.all { it > 1 }

// Print all the elements in row-order
x.forEach { println(it) }

// Print all the elements including their column number
x.forEachIndexed { row, col, ele -> println("\$col \$it") }

// Apply a function to a row at a time and store the outputs in a contiguous matrix
val sins = x.mapRows { row -> sin(row) }

// Print all elements greater than 1
x.each { if (it>1) println(it) }
```

We can also do some linear algebra:

```// Matrix literal syntax, see creators.kt for
// convenience functions like zeros(5,5)
var A = mat[1,0,0 end
0,3,0 end
0,0,4]

// Calculate the matrix inverse
var Ainv = A.inv()

var b = mat[2,2,4].T

// Use overloaded operators:

// * is matrix multiplication
var c = A*b + 1

// emul is element-wise multiplication
var d = (A emul A) + 1

// Number of decimals to show
format("short")

println(c)
```

Which produces:

```Output:

mat[ 3.00  end
7.00  end
17.00 ]
```

Many special functions are supported (see the matrix interface for a complete list):

```val a = 2*eye(3)+.01 // eye is identity matrix

a.chol()  // Cholesky decomposition
a.det()   // Determinant
a.diag()  // Diagonal vector
a.inv()   // Matrix inverse
a.norm()  // Matrix norm
```

Scalar functions can be applied elementwise to matrices (see here for a complete list):

```val x = create(0..100)/5.0  // Matrix of 0, 1/5, 2/5, ...
val y = sin(x)              // Sin applied elementwise
plot(y)                     // Plot of sin function
```

Matrix indexing and slicing is supported (see here for a list of operators as well as the Matrix type):

```val x = randn(5,5)
val y = x[0,0..4] // Grab the first row

x[0..2,0..3] = zeros(3,4) // Set the upper-left 3x4 sub-matrix of x to zero
```

A Matrix is convertible to an Iterable:

```val x = randn(5,5).toIterable()

// Adds all elements and returns sum
x.reduce { x, y -> x+y }

// Returns list of all elements greater than 4
x.find { it > 4 }
```