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

org.ejml.dense.row.SpecializedOps_FDRM Maven / Gradle / Ivy

Go to download

A fast and easy to use dense and sparse matrix linear algebra library written in Java.

There is a newer version: 0.43.1
Show newest version
/*
 * Copyright (c) 2022, Peter Abeles. All Rights Reserved.
 *
 * This file is part of Efficient Java Matrix Library (EJML).
 *
 * 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 org.ejml.dense.row;

import javax.annotation.Generated;
import org.ejml.data.FMatrix1Row;
import org.ejml.data.FMatrixD1;
import org.ejml.data.FMatrixRMaj;
import org.ejml.dense.row.mult.VectorVectorMult_FDRM;
import org.ejml.interfaces.linsol.LinearSolverDense;
import org.jetbrains.annotations.Nullable;

/**
 * This contains less common or more specialized matrix operations.
 *
 * @author Peter Abeles
 */
@Generated("org.ejml.dense.row.SpecializedOps_DDRM")
public class SpecializedOps_FDRM {
    private SpecializedOps_FDRM(){}

    /**
     * 

* Creates a reflector from the provided vector.
*
* Q = I - γ u uT
* γ = 2/||u||2 *

* *

* In practice {@link VectorVectorMult_FDRM#householder(float, FMatrixD1, FMatrixD1, FMatrixD1)} multHouseholder} * should be used for performance reasons since there is no need to calculate Q explicitly. *

* * @param u A vector. Not modified. * @return An orthogonal reflector. */ public static FMatrixRMaj createReflector( FMatrix1Row u ) { if (!MatrixFeatures_FDRM.isVector(u)) throw new IllegalArgumentException("u must be a vector"); float norm = NormOps_FDRM.fastNormF(u); float gamma = -2.0f/(norm*norm); FMatrixRMaj Q = CommonOps_FDRM.identity(u.getNumElements()); CommonOps_FDRM.multAddTransB(gamma, u, u, Q); return Q; } /** *

* Creates a reflector from the provided vector and gamma.
*
* Q = I - γ u uT
*

* *

* In practice {@link VectorVectorMult_FDRM#householder(float, FMatrixD1, FMatrixD1, FMatrixD1)} multHouseholder} * should be used for performance reasons since there is no need to calculate Q explicitly. *

* * @param u A vector. Not modified. * @param gamma To produce a reflector gamma needs to be equal to 2/||u||. * @return An orthogonal reflector. */ public static FMatrixRMaj createReflector( FMatrixRMaj u, float gamma ) { if (!MatrixFeatures_FDRM.isVector(u)) throw new IllegalArgumentException("u must be a vector"); FMatrixRMaj Q = CommonOps_FDRM.identity(u.getNumElements()); CommonOps_FDRM.multAddTransB(-gamma, u, u, Q); return Q; } /** * Creates a copy of a matrix but swaps the rows as specified by the order array. * * @param order Specifies which row in the dest corresponds to a row in the src. Not modified. * @param src The original matrix. Not modified. * @param dst A Matrix that is a row swapped copy of src. Modified. */ public static FMatrixRMaj copyChangeRow( int[] order, FMatrixRMaj src, @Nullable FMatrixRMaj dst ) { if (dst == null) { dst = new FMatrixRMaj(src.numRows, src.numCols); } else if (src.numRows != dst.numRows || src.numCols != dst.numCols) { throw new IllegalArgumentException("src and dst must have the same dimensions."); } for (int i = 0; i < src.numRows; i++) { int indexDst = i*src.numCols; int indexSrc = order[i]*src.numCols; System.arraycopy(src.data, indexSrc, dst.data, indexDst, src.numCols); } return dst; } /** * Copies just the upper or lower triangular portion of a matrix. * * @param src Matrix being copied. Not modified. * @param dst Where just a triangle from src is copied. If null a new one will be created. Modified. * @param upper If the upper or lower triangle should be copied. * @return The copied matrix. */ public static FMatrixRMaj copyTriangle( FMatrixRMaj src, @Nullable FMatrixRMaj dst, boolean upper ) { if (dst == null) { dst = new FMatrixRMaj(src.numRows, src.numCols); } else if (src.numRows != dst.numRows || src.numCols != dst.numCols) { throw new IllegalArgumentException("src and dst must have the same dimensions."); } if (upper) { int N = Math.min(src.numRows, src.numCols); for (int i = 0; i < N; i++) { int index = i*src.numCols + i; System.arraycopy(src.data, index, dst.data, index, src.numCols - i); } } else { for (int i = 0; i < src.numRows; i++) { int length = Math.min(i + 1, src.numCols); int index = i*src.numCols; System.arraycopy(src.data, index, dst.data, index, length); } } return dst; } /** * Performs L = L*LT */ public static void multLowerTranB( FMatrixRMaj mat ) { int m = mat.numCols; float[] L = mat.data; for (int i = 0; i < m; i++) { for (int j = m - 1; j >= i; j--) { float val = 0; for (int k = 0; k <= i; k++) { val += L[i*m + k]*L[j*m + k]; } L[i*m + j] = val; } } // copy the results into the lower portion for (int i = 0; i < m; i++) { for (int j = 0; j < i; j++) { L[i*m + j] = L[j*m + i]; } } } /** * Performs L = LT*L */ public static void multLowerTranA( FMatrixRMaj mat ) { int m = mat.numCols; float[] L = mat.data; for (int i = 0; i < m; i++) { for (int j = m - 1; j >= i; j--) { float val = 0; for (int k = j; k < m; k++) { val += L[k*m + i]*L[k*m + j]; } L[i*m + j] = val; } } // copy the results into the lower portion for (int i = 0; i < m; i++) { for (int j = 0; j < i; j++) { L[i*m + j] = L[j*m + i]; } } } /** *

* Computes the F norm of the difference between the two Matrices:
*
* Sqrt{∑i=1:mj=1:n ( aij - bij)2} *

*

* This is often used as a cost function. *

* * @param a m by n matrix. Not modified. * @param b m by n matrix. Not modified. * @return The F normal of the difference matrix. * @see NormOps_FDRM#fastNormF */ public static float diffNormF( FMatrixD1 a, FMatrixD1 b ) { if (a.numRows != b.numRows || a.numCols != b.numCols) { throw new IllegalArgumentException("Both matrices must have the same shape."); } final int size = a.getNumElements(); FMatrixRMaj diff = new FMatrixRMaj(size, 1); for (int i = 0; i < size; i++) { diff.set(i, b.get(i) - a.get(i)); } return NormOps_FDRM.normF(diff); } public static float diffNormF_fast( FMatrixD1 a, FMatrixD1 b ) { if (a.numRows != b.numRows || a.numCols != b.numCols) { throw new IllegalArgumentException("Both matrices must have the same shape."); } final int size = a.getNumElements(); float total = 0; for (int i = 0; i < size; i++) { float diff = b.get(i) - a.get(i); total += diff*diff; } return (float)Math.sqrt(total); } /** *

* Computes the p=1 p-norm of the difference between the two Matrices:
*
* ∑i=1:mj=1:n | aij - bij|
*
* where |x| is the absolute value of x. *

*

* This is often used as a cost function. *

* * @param a m by n matrix. Not modified. * @param b m by n matrix. Not modified. * @return The p=1 p-norm of the difference matrix. */ public static float diffNormP1( FMatrixD1 a, FMatrixD1 b ) { if (a.numRows != b.numRows || a.numCols != b.numCols) { throw new IllegalArgumentException("Both matrices must have the same shape."); } final int size = a.getNumElements(); float total = 0; for (int i = 0; i < size; i++) { total += Math.abs(b.get(i) - a.get(i)); } return total; } /** *

* Performs the following operation:
*
* B = A + αI *

* * @param A A square matrix. Not modified. * @param B A square matrix that the results are saved to. Modified. * @param alpha Scaling factor for the identity matrix. */ public static void addIdentity( FMatrix1Row A, FMatrix1Row B, float alpha ) { if (A.numCols != A.numRows) throw new IllegalArgumentException("A must be square"); if (B.numCols != A.numCols || B.numRows != A.numRows) throw new IllegalArgumentException("B must be the same shape as A"); int n = A.numCols; int index = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++, index++) { if (i == j) { B.set(index, A.get(index) + alpha); } else { B.set(index, A.get(index)); } } } } /** *

* Extracts a row or column vector from matrix A. The first element in the matrix is at element (rowA,colA). * The next 'length' elements are extracted along a row or column. The results are put into vector 'v' * start at its element v0. *

* * @param A Matrix that the vector is being extracted from. Not modified. * @param rowA Row of the first element that is extracted. * @param colA Column of the first element that is extracted. * @param length Length of the extracted vector. * @param row If true a row vector is extracted, otherwise a column vector is extracted. * @param offsetV First element in 'v' where the results are extracted to. * @param v Vector where the results are written to. Modified. */ public static void subvector( FMatrix1Row A, int rowA, int colA, int length, boolean row, int offsetV, FMatrix1Row v ) { if (row) { for (int i = 0; i < length; i++) { v.set(offsetV + i, A.get(rowA, colA + i)); } } else { for (int i = 0; i < length; i++) { v.set(offsetV + i, A.get(rowA + i, colA)); } } } /** * Takes a matrix and splits it into a set of row or column vectors. * * @param A original matrix. * @param column If true then column vectors will be created. * @return Set of vectors. */ public static FMatrixRMaj[] splitIntoVectors( FMatrix1Row A, boolean column ) { int w = column ? A.numCols : A.numRows; int M = column ? A.numRows : 1; int N = column ? 1 : A.numCols; int o = Math.max(M, N); FMatrixRMaj[] ret = new FMatrixRMaj[w]; for (int i = 0; i < w; i++) { FMatrixRMaj a = new FMatrixRMaj(M, N); if (column) subvector(A, 0, i, o, false, 0, a); else subvector(A, i, 0, o, true, 0, a); ret[i] = a; } return ret; } /** *

* Creates a pivot matrix that exchanges the rows in a matrix: *
* A' = P*A
*

*

* For example, if element 0 in 'pivots' is 2 then the first row in A' will be the 3rd row in A. *

* * @param ret If null then a new matrix is declared otherwise the results are written to it. Is modified. * @param pivots Specifies the new order of rows in a matrix. * @param numPivots How many elements in pivots are being used. * @param transposed If the transpose of the matrix is returned. * @return A pivot matrix. */ public static FMatrixRMaj pivotMatrix( @Nullable FMatrixRMaj ret, int pivots[], int numPivots, boolean transposed ) { if (ret == null) { ret = new FMatrixRMaj(numPivots, numPivots); } else { if (ret.numCols != numPivots || ret.numRows != numPivots) throw new IllegalArgumentException("Unexpected matrix dimension"); CommonOps_FDRM.fill(ret, 0); } if (transposed) { for (int i = 0; i < numPivots; i++) { ret.set(pivots[i], i, 1); } } else { for (int i = 0; i < numPivots; i++) { ret.set(i, pivots[i], 1); } } return ret; } /** * Computes the product of the diagonal elements. For a diagonal or triangular * matrix this is the determinant. * * @param T A matrix. * @return product of the diagonal elements. */ public static float diagProd( FMatrix1Row T ) { float prod = 1.0f; int N = Math.min(T.numRows, T.numCols); for (int i = 0; i < N; i++) { prod *= T.unsafe_get(i, i); } return prod; } /** *

* Returns the absolute value of the digonal element in the matrix that has the largest absolute value.
*
* Max{ |aij| } for all i and j
*

* * @param a A matrix. Not modified. * @return The max abs element value of the matrix. */ public static float elementDiagonalMaxAbs( FMatrixD1 a ) { final int size = Math.min(a.numRows, a.numCols); float max = 0; for (int i = 0; i < size; i++) { float val = Math.abs(a.get(i, i)); if (val > max) { max = val; } } return max; } /** * Computes the quality of a triangular matrix, where the quality of a matrix * is defined in {@link LinearSolverDense#quality()}. In * this situation the quality os the absolute value of the product of * each diagonal element divided by the magnitude of the largest diagonal element. * If all diagonal elements are zero then zero is returned. * * @param T A matrix. * @return the quality of the system. */ public static float qualityTriangular( FMatrixD1 T ) { int N = Math.min(T.numRows, T.numCols); // TODO make faster by just checking the upper triangular portion float max = elementDiagonalMaxAbs(T); if (max == 0.0f) return 0.0f; float quality = 1.0f; for (int i = 0; i < N; i++) { quality *= T.unsafe_get(i, i)/max; } return Math.abs(quality); } /** * Sums up the square of each element in the matrix. This is equivalent to the * Frobenius norm squared. * * @param m Matrix. * @return Sum of elements squared. */ public static float elementSumSq( FMatrixD1 m ) { // minimize round off error float maxAbs = CommonOps_FDRM.elementMaxAbs(m); if (maxAbs == 0) return 0; float total = 0; int N = m.getNumElements(); for (int i = 0; i < N; i++) { float d = m.data[i]/maxAbs; total += d*d; } return maxAbs*total*maxAbs; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy