/*
 * Test program for the classes RowVector and ColumnVector
 *
 * $Date$
 * $Revision$
 *
 */

#ifdef NDEBUG
#undef NDEBUG
#endif /* NDEBUG */

/* turn off debug output from tested class... */
#ifndef DPRINTF
#define DPRINTF(x)
#endif

#include <cassert>
#include <cstring>
#include <iostream>
#include <iomanip>
#include "WImage/debug.h"
#include "../ImageArray.cc"
#include "WImage/RowVector.hh"
#include "WImage/ColumnVector.hh"

#if !(defined __WATCOMC__ && __WATCOMC__ < 1230)
using namespace std;
#endif

static void 
dump (ImageArray<double> *ia)
{
  cout.setf (ios::fixed, ios::floatfield);
  for (int row = 0; row < ia->rows (); row++)
    {
      cout << "[" << std::setw (2) << std::setfill (' ') << row << "] ";
      for (int col = 0; col < ia->cols (); col++)
        {
          cout << std::setprecision (1) << ia->at (row, col) << ' ';
        }
      cout << endl;
    }
  cout.setf (FMT0, ios::floatfield);
}

int
main (void)
{
  cout << "Testing classes RowVector and ColumnVector...\n";

  int x = 3, y = 3;
  ImageArray<double> *ia = NEW (ImageArray<double> (y, x));
  ReferenceVector *rv = NEW (RowVector (ia));
  ReferenceVector *cv = NEW (ColumnVector (ia));

  /*
   * See of error handling in class ReferenceVector works...
   */
  try 
    {
      rv->go (-1);
      assert (0);
    }
  catch (const exception &error)
    {
      cout << "Expected exception caught: " << error.what () << endl;
      assert (strstr (error.what (), "negative") != NULL);
    }

  for (int i = 0; i < ia->size (); i++)
    {
      ia->to (0, i, (double)i);
    }

  /*
   * See if the values are what we expect:
   */
  for (int row = 0; row < ia->rows (); row++)
    {
      if (row != 0)
        {
          rv->go (row);
          assert (rv->root () == row);
        }
      for (int col = 0; col < ia->cols (); col++)
        {
          assert (rv->at (col) == ia->cols () * row + col);
        }
    }
  rv->go (0);
  for (int col = 0; col < ia->cols (); col++)
    {
      if (col != 0)
        {
          cv->go (col);
          assert (cv->root () == col);
        }
      for (int row = 0; row < ia->rows (); row++)
        {
          assert (cv->at (row) == ia->cols () * row + col);
        }
    }
  cv->go (0);

  /*
   * Test at() methods.
   * First the RowVector...
   */
  for (int row = 0; row < ia->rows (); row++)
    {
      if (row != 0)
        {
          rv->go (row);
          assert (rv->root () == row);
        }
      for (int col = 0; col < ia->cols (); col++)
        {
          double val = rv->at (col);
          assert (val == ia->at (row, col));
          rv->to (col, rv->at (col) + 1.0);
          assert ((int)val == (int)ia->at (row, col)-1);
          assert (rv->at (col) == ia->at (row, col));
        }
    }
  
  /*
   * Then the ColumnVector...
   */
  for (int col = 0; col < ia->cols (); col++)
    {
      if (col != 0)
        {
          cv->go (col);
          assert (cv->root () == col);
        }
      for (int row = 0; row < ia->rows (); row++)
        {
          double val = cv->at (row);
          assert (val == ia->at (row, col));
          cv->to (row, cv->at (row) - 1.0);
          assert (!(cv->at (row) < 0.0));
          assert ((int)val == (int)ia->at (row, col)+1);
          assert (cv->at (row) == ia->at (row, col));
        }
    }
  
  dump (ia);

  /*
   * Test the sanity() method...
   */
  assert (rv->sanity ());
  ia->resize (1, 1);
  assert (!rv->sanity ());

  DELETE (ia);
  DELETE (rv);
  DELETE (cv);

  cout << "Test of classes ImageArray and ColumnVector completed successfully."
       << endl;

  return 0;
}
