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

org.ejml.dense.block.MatrixOps_FDRB 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) 2020, 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.block;

import javax.annotation.Generated;
import org.ejml.EjmlParameters;
import org.ejml.UtilEjml;
import org.ejml.data.FGrowArray;
import org.ejml.data.FMatrixRBlock;
import org.ejml.data.FMatrixRMaj;
import org.ejml.data.FSubmatrixD1;
import org.ejml.dense.row.CommonOps_FDRM;
import org.ejml.dense.row.MatrixFeatures_FDRM;
import org.ejml.dense.row.RandomMatrices_FDRM;
import org.ejml.ops.FConvertMatrixStruct;
import org.jetbrains.annotations.Nullable;

import java.util.Random;

//CONCURRENT_MACRO MatrixMult_FDRB MatrixMult_MT_FDRB

/**
 * Various operations on {@link FMatrixRBlock}.
 *
 * @author Peter Abeles
 */
@Generated("org.ejml.dense.block.MatrixOps_DDRB")
public class MatrixOps_FDRB {

    //CONCURRENT_OMIT_BEGIN

    /**
     * Converts a row major matrix into a row major block matrix.
     *
     * @param src Original FMatrixRMaj. Not modified.
     * @param dst Equivalent FMatrixRBlock. Modified.
     */
    public static void convert( FMatrixRMaj src, FMatrixRBlock dst ) {
        FConvertMatrixStruct.convert(src, dst);
    }

    /**
     * Converts a row major matrix into a row major block matrix. Both matrices will contain
     * the same data array. Useful when you wish to avoid declaring two large matrices.
     *
     * @param src Original FMatrixRMaj. Modified.
     * @param dst Equivalent FMatrixRBlock. Modified.
     */
    public static FMatrixRBlock convertInplace( FMatrixRMaj src, @Nullable FMatrixRBlock dst,
                                                @Nullable FGrowArray workspace ) {
        if (dst == null)
            dst = new FMatrixRBlock();

        dst.data = src.data;
        dst.blockLength = EjmlParameters.BLOCK_WIDTH;
        dst.numRows = src.numRows;
        dst.numCols = src.numCols;
        convertRowToBlock(src.numRows, src.numCols, dst.blockLength, src.data, workspace);

        return dst;
    }

    /**
     * 

* Converts matrix data stored is a row major format into a block row major format in place. *

* * @param numRows number of rows in the matrix. * @param numCols number of columns in the matrix. * @param blockLength Block size in the converted matrix. * @param data Matrix data in a row-major format. Modified. * @param workspace Optional internal workspace. Nullable. */ public static void convertRowToBlock( int numRows, int numCols, int blockLength, float[] data, @Nullable FGrowArray workspace ) { int minLength = Math.min(blockLength, numRows)*numCols; float[] tmp = UtilEjml.adjust(workspace, minLength); for (int i = 0; i < numRows; i += blockLength) { int blockHeight = Math.min(blockLength, numRows - i); System.arraycopy(data, i*numCols, tmp, 0, blockHeight*numCols); for (int j = 0; j < numCols; j += blockLength) { int blockWidth = Math.min(blockLength, numCols - j); int indexDst = i*numCols + blockHeight*j; int indexSrcRow = j; for (int k = 0; k < blockHeight; k++) { System.arraycopy(tmp, indexSrcRow, data, indexDst, blockWidth); indexDst += blockWidth; indexSrcRow += numCols; } } } } /** * Converts a row major block matrix into a row major matrix. * * @param src Original FMatrixRBlock.. Not modified. * @param dst Equivalent FMatrixRMaj. Modified. */ public static FMatrixRMaj convert( FMatrixRBlock src, FMatrixRMaj dst ) { return FConvertMatrixStruct.convert(src, dst); } /** * Converts a row major block matrix into a row major matrix. Both matrices will contain * the same data array. Useful when you wish to avoid declaring two large matrices. * * @param src Original FMatrixRBlock. Modified. * @param dst Equivalent FMatrixRMaj. Modified. */ public static FMatrixRMaj convertInplace( FMatrixRBlock src, @Nullable FMatrixRMaj dst, @Nullable FGrowArray workspace ) { if (dst == null) dst = new FMatrixRMaj(); dst.data = src.data; dst.numRows = src.numRows; dst.numCols = src.numCols; convertBlockToRow(src.numRows, src.numCols, src.blockLength, src.data, workspace); return dst; } /** *

* Converts matrix data stored is a block row major format into a row major format in place. *

* * @param numRows number of rows in the matrix. * @param numCols number of columns in the matrix. * @param blockLength Block size in the converted matrix. * @param data Matrix data in a block row-major format. Modified. * @param workspace Optional internal workspace. Nullable. */ public static void convertBlockToRow( int numRows, int numCols, int blockLength, float[] data, @Nullable FGrowArray workspace ) { int minLength = Math.min(blockLength, numRows)*numCols; float[] tmp = UtilEjml.adjust(workspace, minLength); for (int i = 0; i < numRows; i += blockLength) { int blockHeight = Math.min(blockLength, numRows - i); System.arraycopy(data, i*numCols, tmp, 0, blockHeight*numCols); for (int j = 0; j < numCols; j += blockLength) { int blockWidth = Math.min(blockLength, numCols - j); int indexSrc = blockHeight*j; int indexDstRow = i*numCols + j; for (int k = 0; k < blockHeight; k++) { System.arraycopy(tmp, indexSrc, data, indexDstRow, blockWidth); indexSrc += blockWidth; indexDstRow += numCols; } } } } /** * Converts the transpose of a row major matrix into a row major block matrix. * * @param src Original FMatrixRMaj. Not modified. * @param dst Equivalent FMatrixRBlock. Modified. */ public static void convertTranSrc( FMatrixRMaj src, FMatrixRBlock dst ) { if (src.numRows != dst.numCols || src.numCols != dst.numRows) throw new IllegalArgumentException("Incompatible matrix shapes."); for (int i = 0; i < dst.numRows; i += dst.blockLength) { int blockHeight = Math.min(dst.blockLength, dst.numRows - i); for (int j = 0; j < dst.numCols; j += dst.blockLength) { int blockWidth = Math.min(dst.blockLength, dst.numCols - j); int indexDst = i*dst.numCols + blockHeight*j; int indexSrc = j*src.numCols + i; for (int l = 0; l < blockWidth; l++) { int rowSrc = indexSrc + l*src.numCols; int rowDst = indexDst + l; for (int k = 0; k < blockHeight; k++, rowDst += blockWidth) { dst.data[rowDst] = src.data[rowSrc++]; } } } } } //CONCURRENT_OMIT_END // This can be speed up by inlining the multBlock* calls, reducing number of multiplications // and other stuff. doesn't seem to have any speed advantage over mult_reorder() public static void mult( FMatrixRBlock A, FMatrixRBlock B, FMatrixRBlock C ) { if (A.numCols != B.numRows) throw new IllegalArgumentException("Columns in A are incompatible with rows in B"); if (A.numRows != C.numRows) throw new IllegalArgumentException("Rows in A are incompatible with rows in C"); if (B.numCols != C.numCols) throw new IllegalArgumentException("Columns in B are incompatible with columns in C"); if (A.blockLength != B.blockLength || A.blockLength != C.blockLength) throw new IllegalArgumentException("Block lengths are not all the same."); final int blockLength = A.blockLength; FSubmatrixD1 Asub = new FSubmatrixD1(A, 0, A.numRows, 0, A.numCols); FSubmatrixD1 Bsub = new FSubmatrixD1(B, 0, B.numRows, 0, B.numCols); FSubmatrixD1 Csub = new FSubmatrixD1(C, 0, C.numRows, 0, C.numCols); MatrixMult_FDRB.mult(blockLength, Asub, Bsub, Csub); } public static void multTransA( FMatrixRBlock A, FMatrixRBlock B, FMatrixRBlock C ) { if (A.numRows != B.numRows) throw new IllegalArgumentException("Rows in A are incompatible with rows in B"); if (A.numCols != C.numRows) throw new IllegalArgumentException("Columns in A are incompatible with rows in C"); if (B.numCols != C.numCols) throw new IllegalArgumentException("Columns in B are incompatible with columns in C"); if (A.blockLength != B.blockLength || A.blockLength != C.blockLength) throw new IllegalArgumentException("Block lengths are not all the same."); final int blockLength = A.blockLength; FSubmatrixD1 Asub = new FSubmatrixD1(A, 0, A.numRows, 0, A.numCols); FSubmatrixD1 Bsub = new FSubmatrixD1(B, 0, B.numRows, 0, B.numCols); FSubmatrixD1 Csub = new FSubmatrixD1(C, 0, C.numRows, 0, C.numCols); MatrixMult_FDRB.multTransA(blockLength, Asub, Bsub, Csub); } public static void multTransB( FMatrixRBlock A, FMatrixRBlock B, FMatrixRBlock C ) { if (A.numCols != B.numCols) throw new IllegalArgumentException("Columns in A are incompatible with columns in B"); if (A.numRows != C.numRows) throw new IllegalArgumentException("Rows in A are incompatible with rows in C"); if (B.numRows != C.numCols) throw new IllegalArgumentException("Rows in B are incompatible with columns in C"); if (A.blockLength != B.blockLength || A.blockLength != C.blockLength) throw new IllegalArgumentException("Block lengths are not all the same."); final int blockLength = A.blockLength; FSubmatrixD1 Asub = new FSubmatrixD1(A, 0, A.numRows, 0, A.numCols); FSubmatrixD1 Bsub = new FSubmatrixD1(B, 0, B.numRows, 0, B.numCols); FSubmatrixD1 Csub = new FSubmatrixD1(C, 0, C.numRows, 0, C.numCols); MatrixMult_FDRB.multTransB(blockLength, Asub, Bsub, Csub); } //CONCURRENT_OMIT_BEGIN /** * Transposes a block matrix. * * @param A Original matrix. Not modified. * @param A_tran Transposed matrix. Modified. */ public static FMatrixRBlock transpose( FMatrixRBlock A, @Nullable FMatrixRBlock A_tran ) { if (A_tran != null) { if (A.numRows != A_tran.numCols || A.numCols != A_tran.numRows) throw new IllegalArgumentException("Incompatible dimensions."); if (A.blockLength != A_tran.blockLength) throw new IllegalArgumentException("Incompatible block size."); } else { A_tran = new FMatrixRBlock(A.numCols, A.numRows, A.blockLength); } for (int i = 0; i < A.numRows; i += A.blockLength) { int blockHeight = Math.min(A.blockLength, A.numRows - i); for (int j = 0; j < A.numCols; j += A.blockLength) { int blockWidth = Math.min(A.blockLength, A.numCols - j); int indexA = i*A.numCols + blockHeight*j; int indexC = j*A_tran.numCols + blockWidth*i; transposeBlock(A, A_tran, indexA, indexC, blockWidth, blockHeight); } } return A_tran; } /** * Transposes an individual block inside a block matrix. */ private static void transposeBlock( FMatrixRBlock A, FMatrixRBlock A_tran, int indexA, int indexC, int width, int height ) { for (int i = 0; i < height; i++) { int rowIndexC = indexC + i; int rowIndexA = indexA + width*i; int end = rowIndexA + width; for (; rowIndexA < end; rowIndexC += height, rowIndexA++) { A_tran.data[rowIndexC] = A.data[rowIndexA]; } } } public static FMatrixRBlock createRandom( int numRows, int numCols, float min, float max, Random rand ) { FMatrixRBlock ret = new FMatrixRBlock(numRows, numCols); RandomMatrices_FDRM.fillUniform(ret, min, max, rand); return ret; } public static FMatrixRBlock createRandom( int numRows, int numCols, float min, float max, Random rand, int blockLength ) { FMatrixRBlock ret = new FMatrixRBlock(numRows, numCols, blockLength); RandomMatrices_FDRM.fillUniform(ret, min, max, rand); return ret; } public static FMatrixRBlock convert( FMatrixRMaj A, int blockLength ) { FMatrixRBlock ret = new FMatrixRBlock(A.numRows, A.numCols, blockLength); convert(A, ret); return ret; } public static FMatrixRBlock convert( FMatrixRMaj A ) { FMatrixRBlock ret = new FMatrixRBlock(A.numRows, A.numCols); convert(A, ret); return ret; } public static boolean isEquals( FMatrixRBlock A, FMatrixRBlock B ) { if (A.blockLength != B.blockLength) return false; return MatrixFeatures_FDRM.isEquals(A, B); } public static boolean isEquals( FMatrixRBlock A, FMatrixRBlock B, float tol ) { if (A.blockLength != B.blockLength) return false; return MatrixFeatures_FDRM.isEquals(A, B, tol); } /** * Sets either the upper or low triangle of a matrix to zero */ public static void zeroTriangle( boolean upper, FMatrixRBlock A ) { int blockLength = A.blockLength; if (upper) { for (int i = 0; i < A.numRows; i += blockLength) { int h = Math.min(blockLength, A.numRows - i); for (int j = i; j < A.numCols; j += blockLength) { int w = Math.min(blockLength, A.numCols - j); int index = i*A.numCols + h*j; if (j == i) { for (int k = 0; k < h; k++) { for (int l = k + 1; l < w; l++) { A.data[index + w*k + l] = 0; } } } else { for (int k = 0; k < h; k++) { for (int l = 0; l < w; l++) { A.data[index + w*k + l] = 0; } } } } } } else { for (int i = 0; i < A.numRows; i += blockLength) { int h = Math.min(blockLength, A.numRows - i); for (int j = 0; j <= i; j += blockLength) { int w = Math.min(blockLength, A.numCols - j); int index = i*A.numCols + h*j; if (j == i) { for (int k = 0; k < h; k++) { int z = Math.min(k, w); for (int l = 0; l < z; l++) { A.data[index + w*k + l] = 0; } } } else { for (int k = 0; k < h; k++) { for (int l = 0; l < w; l++) { A.data[index + w*k + l] = 0; } } } } } } } /** * Copies either the upper or lower triangular portion of src into dst. Dst can be smaller * than src. * * @param upper If the upper or lower triangle is copied. * @param src The source matrix. Not modified. * @param dst The destination matrix. Modified. */ public static void copyTriangle( boolean upper, FMatrixRBlock src, FMatrixRBlock dst ) { if (src.blockLength != dst.blockLength) throw new IllegalArgumentException("Block size is different"); if (src.numRows < dst.numRows) throw new IllegalArgumentException("The src has fewer rows than dst"); if (src.numCols < dst.numCols) throw new IllegalArgumentException("The src has fewer columns than dst"); int blockLength = src.blockLength; int numRows = Math.min(src.numRows, dst.numRows); int numCols = Math.min(src.numCols, dst.numCols); if (upper) { for (int i = 0; i < numRows; i += blockLength) { int heightSrc = Math.min(blockLength, src.numRows - i); int heightDst = Math.min(blockLength, dst.numRows - i); for (int j = i; j < numCols; j += blockLength) { int widthSrc = Math.min(blockLength, src.numCols - j); int widthDst = Math.min(blockLength, dst.numCols - j); int indexSrc = i*src.numCols + heightSrc*j; int indexDst = i*dst.numCols + heightDst*j; if (j == i) { for (int k = 0; k < heightDst; k++) { for (int l = k; l < widthDst; l++) { dst.data[indexDst + widthDst*k + l] = src.data[indexSrc + widthSrc*k + l]; } } } else { for (int k = 0; k < heightDst; k++) { System.arraycopy(src.data, indexSrc + widthSrc*k, dst.data, indexDst + widthDst*k, widthDst); } } } } } else { for (int i = 0; i < numRows; i += blockLength) { int heightSrc = Math.min(blockLength, src.numRows - i); int heightDst = Math.min(blockLength, dst.numRows - i); for (int j = 0; j <= i; j += blockLength) { int widthSrc = Math.min(blockLength, src.numCols - j); int widthDst = Math.min(blockLength, dst.numCols - j); int indexSrc = i*src.numCols + heightSrc*j; int indexDst = i*dst.numCols + heightDst*j; if (j == i) { for (int k = 0; k < heightDst; k++) { int z = Math.min(k + 1, widthDst); for (int l = 0; l < z; l++) { dst.data[indexDst + widthDst*k + l] = src.data[indexSrc + widthSrc*k + l]; } } } else { for (int k = 0; k < heightDst; k++) { System.arraycopy(src.data, indexSrc + widthSrc*k, dst.data, indexDst + widthDst*k, widthDst); } } } } } } /** *

* Sets every element in the matrix to the specified value.
*
* aij = value *

* * @param A A matrix whose elements are about to be set. Modified. * @param value The value each element will have. */ public static void set( FMatrixRBlock A, float value ) { CommonOps_FDRM.fill(A, value); } /** *

Sets the value of A to all zeros except along the diagonal.

* * @param A Block matrix. */ public static void setIdentity( FMatrixRBlock A ) { int minLength = Math.min(A.numRows, A.numCols); CommonOps_FDRM.fill(A, 0); int blockLength = A.blockLength; for (int i = 0; i < minLength; i += blockLength) { int h = Math.min(blockLength, A.numRows - i); int w = Math.min(blockLength, A.numCols - i); int index = i*A.numCols + h*i; int m = Math.min(h, w); for (int k = 0; k < m; k++) { A.data[index + k*w + k] = 1; } } } /** *

* Returns a new matrix with ones along the diagonal and zeros everywhere else. *

* * @param numRows Number of rows. * @param numCols NUmber of columns. * @param blockLength Block length. * @return An identify matrix. */ public static FMatrixRBlock identity( int numRows, int numCols, int blockLength ) { FMatrixRBlock A = new FMatrixRBlock(numRows, numCols, blockLength); int minLength = Math.min(numRows, numCols); for (int i = 0; i < minLength; i += blockLength) { int h = Math.min(blockLength, A.numRows - i); int w = Math.min(blockLength, A.numCols - i); int index = i*A.numCols + h*i; int m = Math.min(h, w); for (int k = 0; k < m; k++) { A.data[index + k*w + k] = 1; } } return A; } /** *

* Checks to see if the two matrices have an identical shape an block size. *

* * @param A Matrix. * @param B Matrix. */ public static void checkIdenticalShape( FMatrixRBlock A, FMatrixRBlock B ) { if (A.blockLength != B.blockLength) throw new IllegalArgumentException("Block size is different"); if (A.numRows != B.numRows) throw new IllegalArgumentException("Number of rows is different"); if (A.numCols != B.numCols) throw new IllegalArgumentException("NUmber of columns is different"); } /** *

* Extracts a matrix from src into dst. The submatrix which is copied has its initial coordinate * at (0,0) and ends at (dst.numRows,dst.numCols). The end rows/columns must be aligned along blocks * or else it will silently screw things up. *

* * @param src Matrix which a submatrix is being extracted from. Not modified. * @param dst Where the submatrix is written to. Its rows and columns be less than or equal to 'src'. Modified. */ public static void extractAligned( FMatrixRBlock src, FMatrixRBlock dst ) { if (src.blockLength != dst.blockLength) throw new IllegalArgumentException("Block size is different"); if (src.numRows < dst.numRows) throw new IllegalArgumentException("The src has fewer rows than dst"); if (src.numCols < dst.numCols) throw new IllegalArgumentException("The src has fewer columns than dst"); int blockLength = src.blockLength; int numRows = Math.min(src.numRows, dst.numRows); int numCols = Math.min(src.numCols, dst.numCols); for (int i = 0; i < numRows; i += blockLength) { int heightSrc = Math.min(blockLength, src.numRows - i); int heightDst = Math.min(blockLength, dst.numRows - i); for (int j = 0; j < numCols; j += blockLength) { int widthSrc = Math.min(blockLength, src.numCols - j); int widthDst = Math.min(blockLength, dst.numCols - j); int indexSrc = i*src.numCols + heightSrc*j; int indexDst = i*dst.numCols + heightDst*j; for (int k = 0; k < heightDst; k++) { System.arraycopy(src.data, indexSrc + widthSrc*k, dst.data, indexDst + widthDst*k, widthDst); } } } } /** * Checks to see if the submatrix has its boundaries along inner blocks. * * @param blockLength Size of an inner block. * @param A Submatrix. * @return If it is block aligned or not. */ public static boolean blockAligned( int blockLength, FSubmatrixD1 A ) { if (A.col0%blockLength != 0) return false; if (A.row0%blockLength != 0) return false; if (A.col1%blockLength != 0 && A.col1 != A.original.numCols) { return false; } if (A.row1%blockLength != 0 && A.row1 != A.original.numRows) { return false; } return true; } static void checkShapeMult( int blockLength, FSubmatrixD1 A, FSubmatrixD1 B, FSubmatrixD1 C ) { //@formatter:off int Arow = A.getRows(); int Acol = A.getCols(); int Brow = B.getRows(); int Bcol = B.getCols(); int Crow = C.getRows(); int Ccol = C.getCols(); //@formatter:on if (Arow != Crow) throw new RuntimeException("Mismatch A and C rows"); if (Bcol != Ccol) throw new RuntimeException("Mismatch B and C columns"); if (Acol != Brow) throw new RuntimeException("Mismatch A columns and B rows"); if (!MatrixOps_FDRB.blockAligned(blockLength, A)) throw new RuntimeException("Sub-Matrix A is not block aligned"); if (!MatrixOps_FDRB.blockAligned(blockLength, B)) throw new RuntimeException("Sub-Matrix B is not block aligned"); if (!MatrixOps_FDRB.blockAligned(blockLength, C)) throw new RuntimeException("Sub-Matrix C is not block aligned"); } //CONCURRENT_OMIT_END }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy