org.ejml.dense.row.mult.MatrixMatrixMult_FDRM Maven / Gradle / Ivy
Show all versions of ejml-fdense Show documentation
/*
* Copyright (c) 2009-2018, 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.mult;
import org.ejml.MatrixDimensionException;
import org.ejml.data.FMatrix1Row;
import org.ejml.dense.row.CommonOps_FDRM;
/**
*
* This class contains various types of matrix matrix multiplication operations for {@link FMatrix1Row}.
*
*
* Two algorithms that are equivalent can often have very different runtime performance.
* This is because of how modern computers uses fast memory caches to speed up reading/writing to data.
* Depending on the order in which variables are processed different algorithms can run much faster than others,
* even if the number of operations is the same.
*
*
*
* Algorithms that are labeled as 'reorder' are designed to avoid caching jumping issues, some times at the cost
* of increasing the number of operations. This is important for large matrices. The straight forward
* implementation seems to be faster for small matrices.
*
*
*
* Algorithms that are labeled as 'aux' use an auxiliary array of length n. This array is used to create
* a copy of an out of sequence column vector that is referenced several times. This reduces the number
* of cache misses. If the 'aux' parameter passed in is null then the array is declared internally.
*
*
*
* Typically the straight forward implementation runs about 30% faster on smaller matrices and
* about 5 times slower on larger matrices. This is all computer architecture and matrix shape/size specific.
*
*
* ******** IMPORTANT **********
* This class was auto generated using org.ejml.dense.row.mult.GeneratorMatrixMatrixMult_FDRM
*
* @author Peter Abeles
*/
public class MatrixMatrixMult_FDRM {
/**
* @see CommonOps_FDRM#mult( org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row)
*/
public static void mult_reorder( FMatrix1Row a , FMatrix1Row b , FMatrix1Row c )
{
if( a == c || b == c )
throw new IllegalArgumentException("Neither 'a' or 'b' can be the same matrix as 'c'");
else if( a.numCols != b.numRows ) {
throw new MatrixDimensionException("The 'a' and 'b' matrices do not have compatible dimensions");
}
c.reshape(a.numRows,b.numCols);
if( a.numCols == 0 || a.numRows == 0 ) {
CommonOps_FDRM.fill(c,0);
return;
}
float valA;
int indexCbase= 0;
int endOfKLoop = b.numRows*b.numCols;
for( int i = 0; i < a.numRows; i++ ) {
int indexA = i*a.numCols;
// need to assign c.data to a value initially
int indexB = 0;
int indexC = indexCbase;
int end = indexB + b.numCols;
valA = a.get(indexA++);
while( indexB < end ) {
c.set(indexC++ , valA*b.get(indexB++));
}
// now add to it
while( indexB != endOfKLoop ) { // k loop
indexC = indexCbase;
end = indexB + b.numCols;
valA = a.get(indexA++);
while( indexB < end ) { // j loop
c.plus(indexC++ , valA*b.get(indexB++));
}
}
indexCbase += c.numCols;
}
}
/**
* @see CommonOps_FDRM#mult( org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row)
*/
public static void mult_small( FMatrix1Row a , FMatrix1Row b , FMatrix1Row c )
{
if( a == c || b == c )
throw new IllegalArgumentException("Neither 'a' or 'b' can be the same matrix as 'c'");
else if( a.numCols != b.numRows ) {
throw new MatrixDimensionException("The 'a' and 'b' matrices do not have compatible dimensions");
}
c.reshape(a.numRows,b.numCols);
int aIndexStart = 0;
int cIndex = 0;
for( int i = 0; i < a.numRows; i++ ) {
for( int j = 0; j < b.numCols; j++ ) {
float total = 0;
int indexA = aIndexStart;
int indexB = j;
int end = indexA + b.numRows;
while( indexA < end ) {
total += a.get(indexA++) * b.get(indexB);
indexB += b.numCols;
}
c.set( cIndex++ , total );
}
aIndexStart += a.numCols;
}
}
/**
* @see CommonOps_FDRM#mult( org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row)
*/
public static void mult_aux( FMatrix1Row a , FMatrix1Row b , FMatrix1Row c , float []aux )
{
if( a == c || b == c )
throw new IllegalArgumentException("Neither 'a' or 'b' can be the same matrix as 'c'");
else if( a.numCols != b.numRows ) {
throw new MatrixDimensionException("The 'a' and 'b' matrices do not have compatible dimensions");
}
c.reshape(a.numRows,b.numCols);
if( aux == null ) aux = new float[ b.numRows ];
for( int j = 0; j < b.numCols; j++ ) {
// create a copy of the column in B to avoid cache issues
for( int k = 0; k < b.numRows; k++ ) {
aux[k] = b.unsafe_get(k,j);
}
int indexA = 0;
for( int i = 0; i < a.numRows; i++ ) {
float total = 0;
for( int k = 0; k < b.numRows; ) {
total += a.get(indexA++)*aux[k++];
}
c.set( i*c.numCols+j , total );
}
}
}
/**
* @see CommonOps_FDRM#multTransA( org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row, org.ejml.data.FMatrix1Row)
*/
public static void multTransA_reorder( FMatrix1Row a , FMatrix1Row b , FMatrix1Row c )
{
if( a == c || b == c )
throw new IllegalArgumentException("Neither 'a' or 'b' can be the same matrix as 'c'");
else if( a.numRows != b.numRows ) {
throw new MatrixDimensionException("The 'a' and 'b' matrices do not have compatible dimensions");
}
c.reshape(a.numCols,b.numCols);
if( a.numCols == 0 || a.numRows == 0 ) {
CommonOps_FDRM.fill(c,0);
return;
}
float valA;
for( int i = 0; i < a.numCols; i++ ) {
int indexC_start = i*c.numCols;
// first assign R
valA = a.get(i);
int indexB = 0;
int end = indexB+b.numCols;
int indexC = indexC_start;
while( indexB