// matrixAddition2.cpp

#include "textUtility2.h"   // includes <iostream>
#include <fstream>

const int ROWS = 3;
const int COLUMNS = 4;
typedef float Matrix[ROWS][COLUMNS];

bool readMatrices(const char inputFilename[],
                  Matrix matrix1,
                  Matrix matrix2);
void add(const Matrix addend1,
         const Matrix addend2,
         Matrix sum);
bool printMatrix(const Matrix matrix,
                 const char outputFilename[]);

/*
 * int main()
 *
 * Reads two matrices from a text file, adds them,
 * and outputs the result to another text file.
 * Prints appropriate error messages or completion
 * message to the terminal window.
 *
 * Global variable:
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 * Global constants:
 *    ROWS - outer dimension of a 2-dimensional array.
 *    COLUMNS - inner dimension of a 2-dimensional array.
 */
int main()
{
   const char INPUT_FILENAME[] = "matricesToAdd.txt";
   const char OUTPUT_FILENAME[] = "matrixSum.txt";

   Matrix matrix1;
   Matrix matrix2;
   readMatrices(INPUT_FILENAME, matrix1, matrix2);

   Matrix matrixSum;
   add(matrix1, matrix2, matrixSum);
   printMatrix(matrixSum, OUTPUT_FILENAME);

   return 0;
}  // function main

/*
 * bool readMatrices(const char inputFilename[],
 *                   Matrix matrix1,
 *                   Matrix matrix2)
 *
 * Reads two matrices from the specifed text file.
 * If unsuccessful, an error message is output
 * to the terminal window.
 *
 * Parameters:
 *    inputFilename - name of text file containing
 *       two matrices separated by a blank line.
 *    matrix1 - the first matrix in the file.
 *       Precondition: none.
 *       Postcondition:  matrix1 has been read from file.
 *    matrix2 - the second matrix in the file.
 *       Precondition: none.
 *       Postcondition:  matrix2 has been read from file.
 *
 * Global variable:
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 *       Precondition:  The state of cout is true.
 *       Postcondtion:  The state of cout is still true.
 *
 * Global constants:
 *    ROWS - outer dimension of a 2-dimensional array.
 *    COLUMNS - inner dimension of a 2-dimensional array.
 *
 * Returns:
 *    true if both matrices were read successfully,
 *    false otherwise.
 */
bool readMatrices(const char inputFilename[],
                  Matrix matrix1,
                  Matrix matrix2)
{
   // Prepare to read from input file:
   ifstream inputFile;
   inputFile.open(inputFilename);
   if ( !inputFile )  {
      cout << "Could not read file "
                 << inputFilename << "." << endl;
      return false;
   }  // if

   // Read first matrix:
   for ( int i = 0; i < ROWS; i++ )
      for ( int j = 0; j < COLUMNS; j++ )  {
         inputFile >> matrix1[i][j];
         if ( !inputFile )  {
            cout << "Error reading file "
                       << inputFilename << "." << endl;
            return false;
         }  // if
      }  // for j

   // Read second matrix:
   for ( int i = 0; i < ROWS; i++ )
      for ( int j = 0; j < COLUMNS; j++ )  {
         inputFile >> matrix2[i][j];
         if ( !inputFile )  {
            cout << "Error reading file "
                       << inputFilename << "." << endl;
            return false;
         }  // if
      }  // for j

   return true;
}  // function readMatrices

/*
 * void add(const Matrix addend1,
 *          const Matrix addend2,
 *          Matrix sum)
 *
 * Adds two matrices.
 *
 * Parameters:
 *    addend1 - first of 2 matrices to be added.
 *    addend2 - second of 2 matrices to be added.
 *    sum - the result matrix.
 *       Precondition: none.
 *       Postcondition:  sum is the matrix sum
 *          of addend1 and addend2.
 *
 * Global constants:
 *    ROWS - outer dimension of a 2-dimensional array.
 *    COLUMNS - inner dimension of a 2-dimensional array.
 */
void add(const Matrix addend1,
         const Matrix addend2,
         Matrix sum)
{
   for ( int i = 0; i < ROWS; i++ )
      for ( int j = 0; j < COLUMNS; j++ )
         sum[i][j] = addend1[i][j] + addend2[i][j];
}  // function add

/*
 * bool printMatrix(const Matrix matrix,
 *                  const char outputFilename[])
 *
 * Prints a matrix to the specified text file.
 * If successful, a completion message is output
 * to the terminal window.
 * If unsuccessful, an error message is output
 * to the terminal window.
 *
 * Parameters:
 *    matrix - the matrix to be printed.
 *    outpufFliename - name of text file to which matrix
 *       will be printed.
 *
 * Global variable:
 *    cout - an ostream object for output to the terminal.
 *           cout is an external variable, declared
 *           in library header file <iostream>.
 *       Precondition:  The state of cout is true.
 *       Postcondtion:  The state of cout is still true.
 * Global constants:
 *    ROWS - outer dimension of a 2-dimensional array.
 *    COLUMNS - inner dimension of a 2-dimensional array.
 *
 * Returns:
 *    true if the matrix was written successfully to the
 *       output file, false otherwise.
 */
bool printMatrix(const Matrix matrix,
                 const char outputFilename[])
{
   // Prepare to write to output file:
   ofstream outputFile;
   outputFile.open(outputFilename);
   if ( !outputFile )  {
      cout << "Could not write to file "
                 << outputFilename << "." << endl;
      return false;
   }  // if

   // Write matrix to output file:
   for ( int i = 0; i < ROWS; i++ ) {
      for ( int j = 0; j < COLUMNS; j++ )
         printRightJustified(matrix[i][j], 2, 7, outputFile);
      outputFile << endl;
   }  // for i

   cout << "File " << outputFilename
            << " has been created." << endl;

   return true;
}  // function printMatrix