/*
 *  Copyright 2009 OpenSourceStewardshipFoundation.org
 *  Licensed under GNU General Public License version 2
 *
 * Author: seanhalle@yahoo.com
 *
 * Created on November 15, 2009, 2:35 AM
 */

#include <malloc.h>
#include <stdlib.h>

#include "Matrix_Mult.h"
#include "../C_Libraries/ParamHelper/Param.h"


 
 void
initialize_Input_Matrices_Via( Matrix  **leftMatrix, Matrix **rightMatrix,
                               ParamBag *paramBag )
 { char *leftMatrixFileName, *rightMatrixFileName;
   int   leftMatrixRows, leftMatrixCols, rightMatrixRows, rightMatrixCols;
   
      ParamStruc *param;
      param = getParamFromBag( "leftMatrixRows", paramBag );
   leftMatrixRows = param->intValue;
      param = getParamFromBag( "leftMatrixCols", paramBag );
   leftMatrixCols = param->intValue;
   *leftMatrix = makeMatrix_WithResMat( leftMatrixRows, leftMatrixCols );
   
      param = getParamFromBag( "leftMatrixFileName", paramBag );
   leftMatrixFileName = param->strValue;  //no need to copy
   read_Matrix_From_File( *leftMatrix,  leftMatrixFileName );
   
      param = getParamFromBag( "rightMatrixRows", paramBag );
   rightMatrixRows = param->intValue;
      param = getParamFromBag( "rightMatrixCols", paramBag );
   rightMatrixCols = param->intValue;
   *rightMatrix = makeMatrix_WithResMat( rightMatrixRows, rightMatrixCols );
   
      param = getParamFromBag( "rightMatrixFileName", paramBag );
   rightMatrixFileName = param->strValue;
   read_Matrix_From_File( *rightMatrix, rightMatrixFileName );
 }


void parseLineIntoRow( char *line, float32* row );


 void
read_Matrix_From_File( Matrix *matrixStruc, char *matrixFileName )
 { int    row, maxRead, numRows, numCols;
   float32 *matrixStart;
   size_t lineSz = 0;
   FILE  *file;
   char  *line = NULL;
   
   lineSz = 50000; //max length of line in a matrix data file
   line = (char *) malloc( lineSz );
   if( line == NULL ) printf( "no mem for matrix line" );
   
   numRows = matrixStruc->numRows;
   numCols = matrixStruc->numCols;
   matrixStart = matrixStruc->array;

   file = fopen( matrixFileName, "r" );
   if( file == NULL ) { printf( "\nCouldn't open file!!\n"); exit(1);}
   fseek( file, 0, SEEK_SET );
   for( row = 0; row < numRows; row++ )
    {
      if( feof( file ) )  printf( "file ran out too soon" );
      maxRead = getline( &line, &lineSz, file );
      if( maxRead == -1 ) printf( "prob reading mat line");
      
      if( *line == '\n') continue; //blank line
      if( *line == '/' ) continue; //comment line
      
      parseLineIntoRow( line, matrixStart + row * numCols );
    }
   free( line );
 }

/*This function relies on each line having the proper number of cols.  It
 * doesn't check, nor enforce, so if the file is improperly formatted it
 * can write over unrelated memory
 */
 void
parseLineIntoRow( char *line, float32* row )
 {
   char *valueStr, *searchPos;
   
      //read the float values
   searchPos = valueStr = line; //start
   
   for( ; *searchPos != 0; searchPos++)  //bit dangerous, should use buff len
    {
      if( *searchPos == '\n' ) //last col..  relying on well-formatted file
       { *searchPos = 0;
         *row = atof( valueStr );
         break;                                    //end FOR loop
       }
      if( *searchPos == ',' )
       { *searchPos = 0;                           //mark end of string
         *row = (float32) atof( valueStr );
         row += 1;                                 //address arith
            //skip any spaces before digits.. use searchPos + 1 to skip the 0
         for( ; *(searchPos + 1)== ' ' && *(searchPos + 1) !=0; searchPos++);
         valueStr = searchPos + 1;
       }
    }
 }

 //==========================================================================

/*In the "_Flat" version of constructor, do only malloc of the top data struc
 * and set values in that top-level.  Don't malloc any sub-structures.
 */
 Matrix *
makeMatrix_Flat( int32 numRows, int32 numCols )
 { Matrix * retMatrix;
   retMatrix = malloc( sizeof( Matrix ) );
   retMatrix->numRows = numRows;
   retMatrix->numCols = numCols;

   return retMatrix;
 }

 Matrix *
makeMatrix_WithResMat( int32 numRows, int32 numCols )
 { Matrix * retMatrix;
   retMatrix = malloc( sizeof( Matrix ) );
   retMatrix->numRows = numRows;
   retMatrix->numCols = numCols;
   retMatrix->array  = malloc( numRows * numCols * sizeof(float32) );

   return retMatrix;
 }

 void
freeMatrix_Flat( Matrix * matrix )
 { //( matrix );
 }
 void
freeMatrix( Matrix * matrix )
 { free( matrix->array );
   free( matrix );
 }

void
printMatrix( Matrix *matrix )
 { int r, c, numRows, numCols, rowsToPrint, colsToPrint, rowIncr, colIncr;
   float32 *matrixArray;

   numRows = rowsToPrint = matrix->numRows;
   numCols = colsToPrint = matrix->numCols;
   matrixArray = matrix->array;

   rowIncr = numRows/20; if(rowIncr == 0) rowIncr = 1;//20 to 39 rows printed
   colIncr = numCols/20; if(colIncr == 0) colIncr = 1;//20 to 39 cols printed
   for( r = 0; r < numRows; r += rowIncr )
    { for( c = 0; c < numCols; c += colIncr )
       { printf( "%3.1f | ", matrixArray[ r * numCols + c ] );
       }
      printf("\n");
    }
 }

