 #include "ThreadedMatrixMult.h"
 //
//##############################################################################
//                           ThreadedMatrixMult.cpp
//
//                     Class  ThreadedMatrixMult implementation.
//
// Math 157   March, 11, 2009                                         (C) UCLA  
//##############################################################################
//
 ThreadedMatrixMult::ThreadedMatrixMult()
 {
    aData = 0;
    bData = 0;
	cData = 0;	
	
	A = 0;   
	B = 0;
	C = 0; 	
 }
 
 ThreadedMatrixMult::~ThreadedMatrixMult()
 {
    destroyData();	
 }
 
 void ThreadedMatrixMult::setMatrixSize(long matrixSize)
 {
 	destroyData();
 	N = matrixSize;
//
//  Dynamically create an Nsize by Nsize matrix 
// 
    long M = N;
    long i; long j;

    aData = new double[M*N];   // matrix data (contiguous allocation)
    bData = new double[M*N];   
    cData = new double[M*N];
//
//  Set up access pointer arrays  
//  so matrix data can be accessed using [][] notation
//  
//  Row major ordering.
// 
    A    = new double*[M];     
    B    = new double*[M];   
    C    = new double*[M];

    for(i = 0; i < M; i++) A[i] = &aData[i*N];
    for(i = 0; i < M; i++) B[i] = &bData[i*N];
    for(i = 0; i < M; i++) C[i] = &cData[i*N];
//
//  Initialize matrices with data 
//
    for(i = 0; i < M; i++)
    { 
    for(j = 0; j < N; j++)
    {
       C[i][j] = 0.0;
       A[i][j] = 1.0;
       B[i][j] = 1.0;
    }}

    // make A non-symmetric so we have a better test case

    A[1][N] = 0.0;
    
    haltFlag = false;
 }
 //
 // Run carries out the matrix multiplication (without blas).
 //
 // haltFlag can be externally set to stop the calculation.
 //
 void ThreadedMatrixMult::run()
 {   
 	
 	long i; long j; long k;
 	
    for(i = 0; i < N; i++)
    { 
    	
    if(haltFlag == true){return;}
    
    for(j = 0; j < N; j++)
    {
       C[i][j] = 0.0;
       for(k = 0; k < N; k++)
       {
       C[i][j] += A[i][k]*B[k][j];
       }
    }} 
 }
	
	
void ThreadedMatrixMult::stop()
{
	if(isRunning())
	{
		haltFlag = true;   // set the halt flag
		wait();            // wait for thread to finish
		haltFlag = false;  // unset halt flag
	}
}

void ThreadedMatrixMult::destroyData()
{
	if(aData != 0) delete [] aData;
	if(bData != 0) delete [] bData;
	if(cData != 0) delete [] cData;
	
	if(A != 0)  delete [] A;     
	if(B != 0)  delete [] B;    
	if(C != 0)  delete [] C; 
	
}
