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

net.jamu.matrix.MatrixF Maven / Gradle / Ivy

/*
 * Copyright 2019, 2021 Stefan Zobel
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.jamu.matrix;

import net.frobenius.ComputationTruncatedException;
import net.frobenius.NotConvergedException;

/**
 * A {@code MatrixF} is a dense matrix of primitive floats with column-major
 * storage layout. The addressing is zero based. All operations throw a
 * {@code NullPointerException} if any of the method arguments is {@code null}.
 */
public interface MatrixF extends Dimensions, FMatrixBasicOps {

    /**
     * Get the single element as a scalar if this matrix is 1-by-1.
     * 
     * @return the single element as a scalar if this matrix is 1-by-1
     * @throws IllegalStateException
     *             if this matrix is not 1-by-1
     */
    float toScalar();

    /**
     * {@code A = alpha * A}
     * 
     * @param alpha
     *            scaling factor
     * @return {@code A}
     */
    MatrixF scaleInplace(float alpha);

    /**
     * {@code B = alpha * A}
     * 
     * @param alpha
     *            scaling factor
     * @param B
     *            output matrix
     * @return {@code B}
     */
    MatrixF scale(float alpha, MatrixF B);

    /**
     * AT = AT
     * 
     * @param AT
     *            output matrix
     * @return {@code AT}
     */
    MatrixF trans(MatrixF AT);

    /**
     * {@code A = A + B}
     * 
     * @param B
     *            the matrix to be added to this matrix
     * @return {@code A}
     */
    MatrixF addInplace(MatrixF B);

    /**
     * {@code A = A + alpha * B}
     * 
     * @param alpha
     *            scale factor for {@code B}
     * @param B
     *            matrix to be added to this matrix (after scaling)
     * @return {@code A}
     */
    MatrixF addInplace(float alpha, MatrixF B);

    /**
     * {@code C = A + B}
     * 
     * @param B
     *            matrix to be added to this matrix
     * @param C
     *            output matrix for the result
     * @return {@code C}
     */
    MatrixF add(MatrixF B, MatrixF C);

    /**
     * {@code C = A + alpha * B}
     * 
     * @param alpha
     *            scale factor for {@code B}
     * @param B
     *            matrix to be added to this matrix (after scaling)
     * @param C
     *            output matrix for the result
     * @return {@code C}
     */
    MatrixF add(float alpha, MatrixF B, MatrixF C);

    /**
     * {@code C = A * B}
     * 
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF mult(MatrixF B, MatrixF C);

    /**
     * {@code C = alpha * A * B}
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF mult(float alpha, MatrixF B, MatrixF C);

    /**
     * {@code C = A * B + C}. On exit, the matrix {@code C} is overwritten by
     * the result of the operation.
     * 
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF multAdd(MatrixF B, MatrixF C);

    /**
     * {@code C = alpha * A * B + C}. On exit, the matrix {@code C} is
     * overwritten by the result of the operation.
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF multAdd(float alpha, MatrixF B, MatrixF C);

    /**
     * C = AT * BT
     * 
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transABmult(MatrixF B, MatrixF C);

    /**
     * C = alpha * AT * BT
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transABmult(float alpha, MatrixF B, MatrixF C);

    /**
     * C = AT * B
     * 
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transAmult(MatrixF B, MatrixF C);

    /**
     * C = alpha * AT * B
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transAmult(float alpha, MatrixF B, MatrixF C);

    /**
     * C = A * BT
     * 
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transBmult(MatrixF B, MatrixF C);

    /**
     * C = alpha * A * BT
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            output matrix for the result of the multiplication
     * @return {@code C}
     */
    MatrixF transBmult(float alpha, MatrixF B, MatrixF C);

    /**
     * C = AT * BT + C. On exit, the matrix
     * {@code C} is overwritten by the result of the operation.
     * 
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transABmultAdd(MatrixF B, MatrixF C);

    /**
     * C = alpha * AT * BT + C. On exit, the
     * matrix {@code C} is overwritten by the result of the operation.
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transABmultAdd(float alpha, MatrixF B, MatrixF C);

    /**
     * C = AT * B + C. On exit, the matrix {@code C} is
     * overwritten by the result of the operation.
     * 
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transAmultAdd(MatrixF B, MatrixF C);

    /**
     * C = alpha * AT * B + C. On exit, the matrix
     * {@code C} is overwritten by the result of the operation.
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transAmultAdd(float alpha, MatrixF B, MatrixF C);

    /**
     * C = A * BT + C. On exit, the matrix {@code C} is
     * overwritten by the result of the operation.
     * 
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transBmultAdd(MatrixF B, MatrixF C);

    /**
     * C = alpha * A * BT + C. On exit, the matrix
     * {@code C} is overwritten by the result of the operation.
     * 
     * @param alpha
     *            scale factor for the multiplication
     * @param B
     *            matrix whose transpose is to be multiplied from the right
     * @param C
     *            the matrix to add on input, contains the result of the
     *            operation on output
     * @return {@code C}
     */
    MatrixF transBmultAdd(float alpha, MatrixF B, MatrixF C);

    /**
     * Get a newly created copy of this matrix.
     * 
     * @return fresh copy of this matrix
     */
    MatrixF copy();

    /**
     * Set all elements of this matrix to {@code 0.0f} mutating this matrix.
     * 
     * @return this matrix (mutated)
     */
    MatrixF zeroInplace();

    /**
     * Copy the {@code other} matrix into this matrix (mutating this matrix)
     * where the dimensions of {@code other} and {@code this} must be the same.
     * 
     * @param other
     *            matrix whose elements should be copied into this matrix
     * @return this matrix (mutated)
     */
    MatrixF setInplace(MatrixF other);

    /**
     * Let {@code this} be a m-by-n matrix and let {@code B} be a j-by-k matrix.
     * Set the entries on and above the main diagonal in {@code this} matrix
     * from the corresponding entries of the {@code B} matrix and set the
     * entries below the main diagonal in {@code this} matrix to zero (mutating
     * {@code this} matrix).
     * 

* The dimensions of {@code B} must satisfy the conditions {@code k >= n} * ({@code B} must have at least as many columns as {@code this} matrix) and * {@code j >= min(m, n)} ({@code B} must have at least as many rows as the * lesser of the number of rows and columns of {@code this} matrix). * * @param B * matrix whose corresponding entries are copied on and above the * main diagonal of {@code this} matrix * @return this matrix (mutated) */ MatrixF setInplaceUpperTrapezoidal(MatrixF B); /** * Let {@code this} be a m-by-n matrix and let {@code B} be a j-by-k matrix. * Set the entries on and below the main diagonal in {@code this} matrix * from the corresponding entries of the {@code B} matrix and set the * entries above the main diagonal in {@code this} matrix to zero (mutating * {@code this} matrix). *

* The dimensions of {@code B} must satisfy the conditions {@code j >= m} * ({@code B} must have at least as many rows as {@code this} matrix) and * {@code k >= min(m, n)} ({@code B} must have at least as many columns as * the lesser of the number of rows and columns of {@code this} matrix). * * @param B * matrix whose corresponding entries are copied on and below the * main diagonal of {@code this} matrix * @return this matrix (mutated) */ MatrixF setInplaceLowerTrapezoidal(MatrixF B); /** * {@code A = alpha * B} * * @param alpha * scale factor for {@code B} * @param B * matrix to be copied into this matrix after the scalar * multiplication * @return {@code A} */ MatrixF setInplace(float alpha, MatrixF B); /** * Get the matrix element at {@code (row, col)}. * * @param row * row index, zero-based * @param col * column index, zero-based * @return the matrix element at {@code (row, col)} */ float get(int row, int col); /** * Set the matrix element at {@code (row, col)} to {@code val} mutating this * matrix. * * @param row * row index, zero-based * @param col * column index, zero-based * @param val * new value * @return this matrix (mutated) */ MatrixF set(int row, int col, float val); /** * Add {@code val} to the matrix element at {@code (row, col)} mutating this * matrix. * * @param row * row index, zero-based * @param col * column index, zero-based * @param val * the value to add to the element at {@code (row, col)} * @return this matrix (mutated) */ MatrixF add(int row, int col, float val); /** * Copy a submatrix of this matrix into {@code B}. * * @param r0 * initial row index (left upper corner) in this matrix * @param c0 * initial col index (left upper corner) in this matrix * @param r1 * last row index (right lower corner) in this matrix * @param c1 * last col index (right lower corner) in this matrix * @param B * matrix of dimension at least * {@code (r1 - r0 + 1) x (c1 - c0 + 1)} * @param rb * initial row index (left upper corner) in the matrix {@code B} * @param cb * initial col index (left upper corner) in the matrix {@code B} * @return the submatrix {@code B} */ MatrixF submatrix(int r0, int c0, int r1, int c1, MatrixF B, int rb, int cb); /** * Set a submatrix from the values of matrix {@code B} extending from * {@code (rb0, cb0)} to {@code (rb1, cb1)} (the upper left and lower right * corner in {@code B} respectively) at position {@code (r0, c0)} in this * matrix. * * @param r0 * initial row index (left upper corner) in this matrix * @param c0 * initial col index (left upper corner) in this matrix * @param rb0 * initial row index (left upper corner) in the matrix {@code B} * @param cb0 * initial col index (left upper corner) in the matrix {@code B} * @param rb1 * last row index (right lower corner) in the matrix {@code B} * @param cb1 * last col index (right lower corner) in the matrix {@code B} * @param B * the matrix that holds the values to set in this matrix * @return this matrix {@code A} */ MatrixF setSubmatrixInplace(int r0, int c0, MatrixF B, int rb0, int cb0, int rb1, int cb1); /** * Computes the solution ({@code X}) to a real system of linear equations * {@code A * X = B}, where {@code A} is either a {@code n x n} matrix and * {@code X} and {@code B} are {@code n x r} matrices, or where {@code A} is * a {@code n x m} and matrix {@code X} is a {@code m x r} matrix and * {@code B} is a {@code n x r} matrix. * * @param B * matrix with the same number of rows as this matrix {@code A}, * and the same number of columns as {@code X} * @param X * matrix with number of rows equal to the number of columns of * this matrix {@code A}, and the same number of columns as * {@code B} * @return {@code X}, the solution of dimension either {@code n x r} (in the * {@code n x n} case) or {@code m x r} (in the {@code m x n} case). * @throws ComputationTruncatedException * for exactly singular factors in the LU decomposition of a * quadratic matrix or for a non-quadratic matrix that doesn't * have full rank */ MatrixF solve(MatrixF B, MatrixF X); /** * Matrix inverse for quadratic matrices. * * @param inverse * matrix where the inverse is stored. Must have the same * dimension as this matrix * @return the inverse matrix (i.e. the argument {@code inverse}) * @throws IllegalArgumentException * if this matrix is not quadratic or if {@code inverse} has the * wrong dimension * @throws ComputationTruncatedException * for exactly singular factors in the LU decomposition of this * matrix */ MatrixF inv(MatrixF inverse); /** * Compute the Moore-Penrose pseudoinverse. * * @return the Moore-Penrose Pseudo-Inverse * @throws NotConvergedException * if the singular value decomposition did not converge */ MatrixF pseudoInv(); /** * Computes the singular value decomposition of this matrix. * * @param full * controls whether the full decomposition should be computed (if * {@code true}) or the singular values only (if {@code false}) * @return the {@link SvdF} of this matrix, either full or the singular * values only (if {@code full} is set to {@code false}) * @throws NotConvergedException * if the singular value decomposition did not converge */ SvdF svd(boolean full); /** * Computes the economy singular value decomposition of this matrix. * * @return the {@link SvdEconF} of this matrix * @throws NotConvergedException * if the singular value decomposition did not converge */ SvdEconF svdEcon(); /** * Convenience method that computes the singular values of this matrix (this * is the same as calling {@code A.svd(false).getS();}). * * @return array containing the singular values in descending order * @throws NotConvergedException * if the singular value decomposition did not converge * @since 1.2 */ float[] singularValues(); /** * Computes the eigenvalue decomposition of this matrix if it is quadratic. * * @param full * controls whether the (right) eigenvectors should be computed * in addition (if {@code true}) or the eigenvalues only (if * {@code false}) * @return the {@link EvdF} of this matrix, either full or the eigenvalues * only (if {@code full} is set to {@code false}) * @throws IllegalArgumentException * if this matrix is not quadratic * @throws ComputationTruncatedException * if the QR decomposition failed to compute all eigenvalues */ EvdF evd(boolean full); /** * Computes the {@code QR} decomposition of this matrix provided it has at * least as many rows as columns. * * @return the {@link QrdF} QR decomposition of this matrix * @throws IllegalArgumentException * if this matrix has less rows than columns */ QrdF qrd(); /** * Computes the {@code LU} decomposition of this matrix. * * @return the {@link LudF} LU decomposition of this matrix */ LudF lud(); /** * Computes the matrix exponential eA of this matrix * if this matrix is a square matrix. *

* The algorithm uses the Taylor scaling and squaring method from "Bader, * P.; Blanes, S.; Casas, F.: Computing the Matrix Exponential with an * Optimized Taylor Polynomial Approximation. Mathematics 2019, 7, 1174." * * @return the matrix exponential (eA) of this * matrix * @throws IllegalArgumentException * if this matrix is not quadratic */ MatrixF expm(); /** * Copy into a jagged array. * * @return this matrix converted to a jagged array */ float[][] toJaggedArray(); /** * Frobenius norm * * @return sqrt of sum of squares of all elements */ float normF(); /** * Induced 2-norm (a.k.a spectral norm or {@code l}2 operator * norm) which happens to correspond to the largest singular value. * * @return maximum singular value * @throws NotConvergedException * if the singular value decomposition did not converge */ float norm2(); /** * Returns the largest absolute value of this matrix (i.e., the "max norm"). * Note that this norm is not submultiplicative. * * @return the largest absolute value of all elements */ float normMaxAbs(); /** * Infinity norm (maximum absolute row sum) * * @return maximum absolute row sum */ float normInf(); /** * 1-norm (maximum absolute column sum) * * @return maximum absolute column sum */ float norm1(); /** * Matrix trace of a square matrix. * * @return sum of the diagonal elements * @throws IllegalArgumentException * if this matrix is not quadratic */ float trace(); /** * Set all elements |xij| <= k * 2-24 * ({@code k} times the machine epsilon for floats) to {@code 0.0f} where * {@code k} is a positive integer {@code >= 1}. * * @param k * positive integer {@code >= 1} * @return this matrix zeroed in-place * @throws IllegalArgumentException * if {@code k < 1} */ MatrixF zeroizeSubEpsilonInplace(int k); /** * Set all elements that are either NaN, positive or negative infinity to * the respective ersatz value provided by the {@code nanSurrogate}, * {@code posInfSurrogate} and {@code negInfSurrogate} arguments. This is a * destructive operation that changes this matrix inplace. * * @param nanSurrogate * the substitution value to use for NaN values * @param posInfSurrogate * the substitution value to use for positive infinity values * @param negInfSurrogate * the substitution value to use for negative infinity values * @return this matrix changed inplace */ MatrixF sanitizeNonFiniteInplace(float nanSurrogate, float posInfSurrogate, float negInfSurrogate); /** * Set all elements that are NaN to the ersatz value provided by the * {@code nanSurrogate} argument. This is a destructive operation that * changes this matrix inplace. * * @param nanSurrogate * the substitution value to use for NaN values * @return this matrix changed inplace */ MatrixF sanitizeNaNInplace(float nanSurrogate); /** * Subtracts the mean of each column {@code j} from each value in that * column {@code j}, effectively centering each column around its mean * (de-meaning that column so that its mean is zero). This is a destructive * operation that changes this matrix inplace. * * @return this matrix de-meaned inplace * @since 1.2 */ MatrixF centerInplace(); /** * Get the reference to the internal backing array without copying. * * @return the reference to the internal backing array */ float[] getArrayUnsafe(); /** * Get the matrix element {@code (row, col)} without bounds checking. * * @param row * row index, zero-based * @param col * column index, zero-based * @return the matrix element at {@code (row, col)} */ float getUnsafe(int row, int col); /** * Set the matrix element at {@code (row, col)} to {@code val} without * bounds checking. * * @param row * row index, zero-based * @param col * column index, zero-based * @param val * new value */ void setUnsafe(int row, int col, float val); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy