package com.data.struct;
import java.util.concurrent.CountDownLatch;
public class MultiThreadRecuisiveMatrixMultipy {
static int[][] a = new int[][] { { 1, 2, 3, 4 }, { 5, 6, 7, 8 },
{ 9, 10, 11, 12 }, { 13, 14, 15, 16 } };
static int[][] b = new int[][] { { 1, 3, 5, 7 }, { 2, 4, 6, 8 },
{ 11, 13, 15, 17 }, { 12, 14, 16, 18 } };
static int[][] c = new int[a.length][a.length];
private static int[][] recruciveMultipy(int [][]a,int[][]b,int[][] indexA,int[][]indexB,int size,CountDownLatch cdl){
int [][] c=new int[size][size];
if(indexA[0][0]-indexA[3][0]==0){
c[indexA[0][0]][indexB[0][1]]=a[indexA[0][0]][indexA[0][1]]*b[indexB[0][0]][indexB[0][1]];
//System.out.println(indexA[0][0]+":"+indexB[0][1]+"="+c[indexA[0][0]][indexB[0][1]]);
}else{
int n=size;
int[][] indexA11=new int[4][2];
indexA11[0][0]=indexA[0][0];
indexA11[0][1]=indexA[0][1];
indexA11[1][0]=indexA[1][0];
indexA11[1][1]=(indexA[1][1]+indexA[0][1])/2;
indexA11[2][0]=(indexA[2][0]+indexA[0][0])/2;
indexA11[2][1]=indexA[2][1];
indexA11[3][0]=(indexA[3][0]+indexA[0][0])/2;
indexA11[3][1]=(indexA[3][1]+indexA[0][1])/2;
int [][]indexA12=new int[4][2];
indexA12[0][0]=indexA[0][0];
indexA12[0][1]=(indexA[1][1]+indexA[0][1])/2+1;
indexA12[1][0]=indexA[1][0];
indexA12[1][1]=indexA[1][1];
indexA12[2][0]=(indexA[3][0]+indexA[0][0])/2;
indexA12[2][1]=(indexA[3][1]+indexA[0][1])/2+1;
indexA12[3][0]=(indexA[3][0]+indexA[0][0])/2;
indexA12[3][1]=indexA[3][1];
int [][] indexA21=new int[4][2];
indexA21[0][0]=(indexA[2][0]+indexA[0][0])/2+1;
indexA21[0][1]=indexA[0][1];
indexA21[1][0]=(indexA[3][0]+indexA[0][0])/2+1;
indexA21[1][1]=(indexA[3][1]+indexA[0][0])/2;
indexA21[2][0]=indexA[2][0];
indexA21[2][1]=indexA[2][1];
indexA21[3][0]=indexA[3][0];
indexA21[3][1]=(indexA[3][1]+indexA[0][0])/2;
int[][]indexA22=new int[4][2];
indexA22[0][0]=(indexA[3][0]+indexA[0][0])/2+1;
indexA22[0][1]=(indexA[3][1]+indexA[0][1])/2+1;
indexA22[1][0]=(indexA[3][0]+indexA[0][0])/2+1;
indexA22[1][1]=indexA[3][1];
indexA22[2][0]=indexA[3][0];
indexA22[2][1]=(indexA[3][1]+indexA[0][1])/2+1;
indexA22[3][0]=indexA[3][0];
indexA22[3][1]=indexA[3][1];
int[][]indexB11=new int[4][2];
indexB11[0][0]=indexB[0][0];
indexB11[0][1]=indexB[0][1];
indexB11[1][0]=indexB[1][0];
indexB11[1][1]=(indexB[1][1]+indexB[0][1])/2;
indexB11[2][0]=(indexB[2][0]+indexB[0][0])/2;
indexB11[2][1]=indexB[2][1];
indexB11[3][0]=(indexB[3][0]+indexB[0][0])/2;
indexB11[3][1]=(indexB[3][1]+indexB[0][1])/2;
int[][]indexB12=new int[4][2];
indexB12[0][0]=indexB[0][0];
indexB12[0][1]=(indexB[1][1]+indexB[0][1])/2+1;
indexB12[1][0]=indexB[1][0];
indexB12[1][1]=indexB[1][1];
indexB12[2][0]=(indexB[3][0]+indexB[0][0])/2;
indexB12[2][1]=(indexB[3][1]+indexB[0][1])/2+1;
indexB12[3][0]=(indexB[3][0]+indexB[0][0])/2;
indexB12[3][1]=indexB[3][1];
int[][]indexB21=new int[4][2];
indexB21[0][0]=(indexB[2][0]+indexB[0][0])/2+1;
indexB21[0][1]=indexB[0][1];
indexB21[1][0]=(indexB[3][0]+indexB[0][0])/2+1;
indexB21[1][1]=(indexB[3][1]+indexB[0][0])/2;
indexB21[2][0]=indexB[2][0];
indexB21[2][1]=indexB[2][1];
indexB21[3][0]=indexB[3][0];
indexB21[3][1]=(indexB[3][1]+indexB[0][0])/2;
int[][]indexB22=new int[4][2];
indexB22[0][0]=(indexB[3][0]+indexB[0][0])/2+1;
indexB22[0][1]=(indexB[3][1]+indexB[0][1])/2+1;
indexB22[1][0]=(indexB[3][0]+indexB[0][0])/2+1;
indexB22[1][1]=indexB[3][1];
indexB22[2][0]=indexB[3][0];
indexB22[2][1]=(indexB[3][1]+indexB[0][1])/2+1;
indexB22[3][0]=indexB[3][0];
indexB22[3][1]=indexB[3][1];
RecruciveMultipyThread t1=new RecruciveMultipyThread(a,b,indexA11,indexB11,size,cdl);
t1.start();
RecruciveMultipyThread t2=new RecruciveMultipyThread(a,b,indexA12,indexB21,size,cdl);
t2.start();
RecruciveMultipyThread t3=new RecruciveMultipyThread(a,b,indexA11,indexB12,size,cdl);
t3.start();
RecruciveMultipyThread t4=new RecruciveMultipyThread(a,b,indexA12,indexB22,size,cdl);
t4.start();
RecruciveMultipyThread t5=new RecruciveMultipyThread(a,b,indexA21,indexB11,size,cdl);
t5.start();
RecruciveMultipyThread t6=new RecruciveMultipyThread(a,b,indexA22,indexB21,size,cdl);
t6.start();
RecruciveMultipyThread t7=new RecruciveMultipyThread(a,b,indexA21,indexB12,size,cdl);
t7.start();
RecruciveMultipyThread t8=new RecruciveMultipyThread(a,b,indexA22,indexB22,size,cdl);
t8.start();
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
int [][]c11x=t1.getC();
int [][]c11y=t2.getC();
int[][]c12x=t3.getC();
int[][]c12y=t4.getC();
int[][]c21x=t5.getC();
int[][]c21y=t6.getC();
int[][]c22x=t7.getC();
int[][]c22y=t8.getC();
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c[i][j]+=c11x[i][j]+c11y[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c[i][j]+=c12x[i][j]+c12y[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c[i][j]+=c21x[i][j]+c21y[i][j];
}
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
c[i][j]+=c22x[i][j]+c22y[i][j];
}
}
}
return c;
}
private static class RecruciveMultipyThread extends Thread{
private int[][]a;
private int[][]b;
private int[][]indexA;
private int[][]indexB;
private int size;
private int[][]c;
private CountDownLatch cdl;
public RecruciveMultipyThread(int[][]a,int[][]b,int [][]indexA,int[][] indexB,int size,CountDownLatch cdl){
this.a=a;
this.b=b;
this.indexA=indexA;
this.indexB=indexB;
this.size=size;
this.cdl=cdl;
}
@Override
public void run() {
CountDownLatch cdl2=new CountDownLatch(8);
c=recruciveMultipy(a,b,indexA,indexB,size,cdl2);
cdl.countDown();
}
public int[][] getC() {
return c;
}
}
public static void printC(){
for(int i=0;i<c.length;i++){
for(int j=0;j<c[i].length;j++){
System.out.print(c[i][j]+" ");
}
System.out.println();
}
}
public static void main(String[] args) {
CountDownLatch cdl=new CountDownLatch(8);
c=recruciveMultipy(a,b,new int[][]{
{0,0},
{0,a.length-1},
{a.length-1,0},
{a.length-1,a.length-1}
},new int[][]{
{0,0},
{0,a.length-1},
{a.length-1,0},
{a.length-1,a.length-1}
},a.length,cdl);
try {
cdl.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
printC();
}
}