All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tecacet.math.extensions.MatrixExtensions.kt Maven / Gradle / Ivy

Go to download

Koltin extensions for matrix and vector algebra, random number generation, and arithmetic on boolean arrays.

The newest version!
package com.tecacet.math.extensions

import java.util.*

typealias Vector = DoubleArray
typealias Matrix = Array

//VECTOR OPERATIONS

operator fun DoubleArray.unaryMinus() = this.map { -it }.toDoubleArray()

/**
 * vector scalar multiplication
 */
operator fun DoubleArray.times(scalar: Number) = this.map { v -> v * scalar.toDouble() }.toDoubleArray()

/**
 * scalar vector multiplication
 */
operator fun Number.times(x: DoubleArray) = x * this

/**
 * vector scalar division
 */
operator fun DoubleArray.div(scalar: Number) = this.map { v -> v / scalar.toDouble() }.toDoubleArray()

/**
 * Vector Addition
 * WARNING: Unless explicitly imported, + defaults to array concatenation
 */
operator fun DoubleArray.plus(x: DoubleArray) = this.indices.map { this[it] + x[it] }.toDoubleArray()

/**
 * Vector subtraction
 */
operator fun DoubleArray.minus(x: DoubleArray) = this.indices.map { this[it] - x[it] }.toDoubleArray()

/**
 * Inner Product
 */
operator fun DoubleArray.times(v: DoubleArray) = this.indices.map { this[it] * v[it] }.sum()

/**
 * Inner Product with int array
 */
operator fun DoubleArray.times(v: IntArray) = this.indices.map { this[it] * v[it] }.sum()

/**
 * First index that achieves the maximum value
 */
fun DoubleArray.argmax() = (0 until this.size).maxBy { this[it] }

fun DoubleArray.normSquared() = this * this
fun DoubleArray.norm() = Math.sqrt(this.normSquared())

/**
 * Create a vector of ones
 */
fun ones(dimension: Int) = DoubleArray(dimension) { 1.0 }

/**
 * Create a vector of zeros
 */
fun zeros(dimension: Int) = DoubleArray(dimension) { 0.0 }

/**
 * Create a coordinate vector of dimension dimension with 1 in index and 0 elsewhere
 * @param dimension the dimension of the vector
 * @param index the index to set to 1
 */
fun coordinate(dimension: Int, index: Int): DoubleArray {
    val v = DoubleArray(dimension) { 0.0 }
    v[index] = 1.0
    return v
}

fun toString(v: Vector): String = Arrays.toString(v)

//MATRIX OPERATIONS

/**
 * Get the ith row of a matrix
 */
fun Array.row(i: Int) = this[i]

/**
 * Number of rows
 */
fun Array.rows() = this.size

/**
 * Number of columns
 */
fun Array.columns() = if (this.isEmpty()) 0 else this[0].size

/**
 * Matrix-scalar multiplication
 */
operator fun Array.times(scalar: Number): Array {
    val X = doubleMatrix(this.rows(), this.columns())
    for (i in 0 until this.rows()) {
        for (j in 0 until this.columns()) {
            X[i][j] = this[i][j] * scalar.toDouble()
        }
    }
    return X
}

operator fun Array.unaryMinus() = this * -1

/**
 * Scalar-matrix multiplication
 */
operator fun Number.times(A: Array): Array = A * this

/**
 * Matrix-scalar division
 */
operator fun Array.div(scalar: Number) = this.times(1.0 / scalar.toDouble())

/**
 * Convert an IntArray to DoubleArray
 */
fun IntArray.toDoubleArray() = this.map { it.toDouble() }.toDoubleArray()


/**
 * Add two matrices
 */
operator fun Array.plus(A: Array): Array {
    val X = doubleMatrix(this.rows(), this.columns())
    for (i in 0 until this.rows()) {
        for (j in 0 until this.columns()) {
            X[i][j] = this[i][j] + A[i][j]
        }
    }
    return X
}

/**
 * Subtract two matrices
 */
operator fun Array.minus(A: Array): Array {
    val X = doubleMatrix(this.rows(), this.columns())
    for (i in 0 until this.rows()) {
        for (j in 0 until this.columns()) {
            X[i][j] = this[i][j] - A[i][j]
        }
    }
    return X
}

/**
 * Matrix-vector multiplication
 */
operator fun Array.times(x: DoubleArray): DoubleArray {
    if (this.columns() != x.size) throw IllegalArgumentException("Incompatible sizes")
    return (0 until this.rows()).map { this[it] * x }.toDoubleArray()
}

/**
 * Matrix multiplication
 */
operator fun Matrix.times(A: Matrix): Matrix {
    if (rows() != A.columns()) throw IllegalArgumentException("Incompatible dimensions")
    return (0 until this.rows()).map { this[it] * A }.toTypedArray()
}

/**
 * Matrix multiplication with vector of integers
 */
operator fun Array.times(x: IntArray): DoubleArray = this * x.toDoubleArray()

/**
 * Vector-matrix multiplication
 */
operator fun DoubleArray.times(A: Array): DoubleArray {
    if (this.size != A.rows()) throw IllegalArgumentException("Incompatible sizes")
    val y = DoubleArray(A.columns())
    for (j in 0 until A.rows()) {
        for (i in 0 until A.columns()) {
            y[i] += A[j][i] * this[j]
        }
    }
    return y
}

/**
 * Transpose matrix
 */
fun Array.transpose(): Array {
    if (this.isEmpty()) {
        return this
    }
    val t = doubleMatrix(this.columns(), this.rows())
    for (i in 0 until this.columns()) {
        for (j in 0 until this.rows()) {
            t[i][j] = this[j][i]
        }
    }
    return t
}

fun toString(matrix: Array): String {
    return (0 until matrix.rows()).map { toString(matrix[it]) }.joinToString("\n")
}

/**
 * Create a unit matrix of the given dimension
 */
fun unit(dimension: Int) = Array(dimension) { i -> DoubleArray(dimension) { j -> if (i == j) 1.0 else 0.0 } }

//double array initialization
fun intMatrix(sizeOuter: Int, sizeInner: Int): Array = Array(sizeOuter) { IntArray(sizeInner) }
fun doubleMatrix(sizeOuter: Int, sizeInner: Int): Array = Array(sizeOuter) { DoubleArray(sizeInner) }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy