/**
* Matrix Multiplication main class.
* @author Heinz Kredel.
*/
public class MatMult {
/**
* Performs a subtraction operation between two arrays sequentially.
* @param C result matrix = A-B.
* @param A left matrix.
* @param B right matirx.
*/
public void seqdiff(double[][] C, double[][] A, double[][] B) {
for (int i=0; i < C.length; i++) {
for (int j=0; j < C[0].length; j++) {
C[i][j] = A[i][j] - B[i][j];
}
}
}
/**
* Performs a transpose operation of the matrix.
* Must be a square matrix.
* @param A matrix.
*/
public void transposeInplace(double[][] A) {
for (int i=0; i < A.length; i++) {
for (int j=i+1; j < A[0].length; j++) {
double aij = A[i][j];
A[i][j] = A[j][i];
A[j][i] = aij;
}
}
}
/**
* Performs a transpose operation of the matrix.
* If A is n x m then B must be m x n.
* @param A Array.
* @param B Array transpose(A).
*/
public void transpose(double[][] B, double[][] A) {
for (int i=0; i < A.length; i++) {
for (int j=i+1; j < A[0].length; j++) {
B[j][i] = A[i][j];
}
}
}
/**
* Generates a matrix.
* Creates a two dimensional array A
with the dimension n, m.
* The method random
returns a
* random number within the intervall [0,1].
* @param n dimension of matrix.
* @param m dimension of matrix.
*/
public double[][] matgen(int n, int m) {
double A[][] = new double[n][m];
for (int i=0; i < n; i++) {
for (int j=0; j < m; j++) {
A[i][j] = Math.random();
}
}
return A;
}
/**
* Generates the null-matrix.
* @param n dimension of matrix.
* @param m dimension of matrix.
*/
public double[][] matgen0(int n, int m) {
double A[][] = new double[n][m];
for (int i=0; i < n; i++) {
for (int j=0; j < m; j++) {
A[i][j] = 0.0;
}
}
return A;
}
/**
* Generates the unit-matrix.
* @param n dimension of matrix.
* @param m dimension of matrix.
*/
public double[][] matgen1(int n, int m) {
double A[][] = new double[n][m];
for (int i=0; i < n; i++) {
for (int j=0; j < m; j++) {
if (i == j) A[i][j] = 1.0; else A[i][j]= 0.0;
}
}
return A;
}
/**
* Prints out the rows of matrix.
* @param A Array.
*/
public void matprint(double[][] A) {
for (int i=0; i < A.length; i++) {
for (int j=0; j < A[0].length; j++) {
System.out.print(A[i][j] + " ");
}
System.out.println();
}
}
/**
* Checks if the matrix is approximatly zero.
* Checks if the absolut value of the matrix's elements are less than
* the production of the smallest positive value and 1000.
* @param A Two dimensional array.
*/
public boolean matcheck0(double[][] A) {
double eps = Double.MIN_VALUE*1000.0;
for (int i=0; i < A.length; i++) {
for (int j=0; j < A[0].length; j++) {
if ( Math.abs(A[i][j]) > eps) {
System.out.println("(i,j)=("+i+","+j+") = "+ A[i][j]);
return false;
}
}
}
return true;
}
/**
* main
*/
public static void main(String[] args) {
int m = 2, // rows of A
n = 4, // columns of B
p = 3; // columns of A = rows of B
boolean prnt = false;
try { m = Integer.parseInt(args[0]);
} catch (Exception e) { }
try { n = Integer.parseInt(args[1]);
} catch (Exception e) { }
try { p = Integer.parseInt(args[2]);
} catch (Exception e) { }
try { prnt = Boolean.valueOf(args[3]).booleanValue();
} catch (Exception e) { }
MatMult x = new MatMult();
MMInf seq = new SeqMult();
MMInf seqb1 = new SeqMultBlock(15);
MMInf seqb2 = new SeqMultBlock(20);
MMInf seqb3 = new SeqMultBlock(25);
MMInf seqt = new SeqMultTrans();
MMInf seqbt = new SeqMultBlockTrans(20);
MMInf seq3 = new SeqMult3();
MMInf seq4 = new SeqMult4(30);
MMInf par = new ParMult();
MMInf parp = new ParMultProc(4);
MMInf parpb = new ParMultProcBlock(4,20);
MMInf parpb1 = new ParMultProcBlock(4,10);
MMInf parpt = new ParMultProcTrans(4);
MMInf parpbt = new ParMultProcBlockTrans(4,20);
MMInf con = new ConMult(4);
MMInf conpbt = new ConMultProcBlockTrans(4,20);
//double[][] A = x.matgen1(m,p);
double[][] A = x.matgen(m,p);
double[][] B = x.matgen(p,n);
//double[][] B = x.matgen1(p,n);
double[][] C = x.matgen0(m,n);
double[][] Cs = x.matgen0(m,n);
double[][] D = x.matgen0(m,n);
System.out.println("Matrix size: " + m + " x " + p + " x " + n);
long flop = 1L * ((long)m) * (2L*(long)p) * ((long)n);
// mult + add
long mflop = flop / 1000000L;
System.out.println("Operations: " + mflop + " MFLOP");
if (prnt) {
System.out.println("A = ");
x.matprint(A);
System.out.println("");
}
if (prnt) {
System.out.println("B = ");
x.matprint(B);
System.out.println("");
}
long tm;
tm = System.currentTimeMillis();
seq.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
C = x.matgen0(m,n);
tm = System.currentTimeMillis();
seqb2.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
if ( n == p ) {
C = x.matgen0(m,n);
tm = System.currentTimeMillis();
x.transposeInplace(B);
seqt.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
x.transposeInplace(B); // required to count in next case
tm = System.currentTimeMillis();
x.transposeInplace(B);
seqbt.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
}
/*
tm = System.currentTimeMillis();
seq4.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
tm = System.currentTimeMillis();
seq3.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
tm = System.currentTimeMillis();
seqb1.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
tm = System.currentTimeMillis();
seqb3.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
*/
Cs = (double[][])C.clone();
C = x.matgen0(m,n);
tm = System.currentTimeMillis();
par.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
tm = System.currentTimeMillis();
parp.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
tm = System.currentTimeMillis();
parpb.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
/*
tm = System.currentTimeMillis();
parpb1.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
*/
if ( n == p ) {
tm = System.currentTimeMillis();
x.transposeInplace(B);
parpt.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
x.transposeInplace(B); // required to count in next case
tm = System.currentTimeMillis();
x.transposeInplace(B);
parpbt.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
}
tm = System.currentTimeMillis();
con.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
if ( n == p ) {
tm = System.currentTimeMillis();
x.transposeInplace(B);
conpbt.multiply(C,A,B);
tm = System.currentTimeMillis() - tm;
System.out.println(tm + " ms, " + ((mflop*1000L/tm)) + " MFLOPS");
}
if (prnt) {
System.out.println("Cs = ");
x.matprint(Cs);
System.out.println("");
}
if (prnt) {
System.out.println("C = ");
x.matprint(C);
System.out.println("");
}
x.seqdiff(D,Cs,C);
if (prnt) {
System.out.println("D = ");
x.matprint(D);
System.out.println("");
}
System.out.println("D is zero = " + x.matcheck0(D) );
}
}