/*
 * Test program for the class VectorPosition
 *
 * $Date$
 * $Revision$
 *
 */

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

#include "Wave/MirrorPosition.hh"
#include "Wave/PeriodicPosition.hh"
#include <cassert>
#include <iostream>

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

int
main (void)
{
  cout << "Testing class VectorPosition...\n";
  int val, sign;

  VectorPosition *pad = NEW (MirrorPosition (8));
  pad->setsymm (true);
  
  cout << "MirrorPosition...\n";

  cout << "false/false...\n  ";
  for (int i = -10; i < 15; i++)
    {
      if (i == 0 || i == 4)
        {
          cout << " |  ";
        }
      val = pad->pos (i, 2, 4, sign);
      
      cout << sign * val << ' ';
    }
  cout << endl;

  assert (pad->pos (-1) == 1);
  assert (pad->pos (-6, 0, 4) == 0);
  assert (pad->pos (-5, 0, 4) == 1);
  assert (pad->pos (-4, 0, 4) == 2);
  assert (pad->pos (-3, 0, 4) == 3);
  assert (pad->pos (-2, 0, 4) == 2);
  assert (pad->pos (-1, 0, 4) == 1);
  assert (pad->pos (4, 0, 4) == 2);
  assert (pad->pos (5, 0, 4) == 1);
  assert (pad->pos (6, 0, 4) == 0);
  assert (pad->pos (7, 0, 4) == 1);
  assert (pad->pos (8, 0, 4) == 2);
  assert (pad->pos (9, 0, 4) == 3);
  assert (pad->pos (10, 0, 4) == 2);
  assert (pad->pos (11, 0, 4) == 1);
  assert (pad->pos (12, 0, 4) == 0);
  assert (pad->pos (pad->size ()) == pad->pos (pad->size () - 2));
  assert (pad->pos (pad->size () + 1) == pad->pos (pad->size () - 3));
  assert (pad->pos (2, 2) == 0);
  assert (pad->pos (-2, 2) == 0);
  assert (pad->pos (-1, 1, 2) == 2);

  ((MirrorPosition*)pad)->setlaxis (true);
  ((MirrorPosition*)pad)->setraxis (true);

  cout << "true/true...\n   ";
  for (int i = -10; i < 15; i++)
    {
      if (i == 0 || i == 4)
        {
          cout << " |  ";
        }
      val = pad->pos (i, 2, 4, sign);
      
      cout << sign * val << ' ';
    }
  cout << endl;

  assert (pad->pos (-1) == 0);
  assert (pad->pos (-6, 0, 4) == 2);
  assert (pad->pos (-5, 0, 4) == 3);
  assert (pad->pos (-4, 0, 4) == 3);
  assert (pad->pos (-3, 0, 4) == 2);
  assert (pad->pos (-2, 0, 4) == 1);
  assert (pad->pos (-1, 0, 4) == 0);
  assert (pad->pos (4, 0, 4) == 3);
  assert (pad->pos (5, 0, 4) == 2);
  assert (pad->pos (6, 0, 4) == 1);
  assert (pad->pos (7, 0, 4) == 0);
  assert (pad->pos (8, 0, 4) == 0);
  assert (pad->pos (9, 0, 4) == 1);
  assert (pad->pos (10, 0, 4) == 2);
  assert (pad->pos (11, 0, 4) == 3);
  assert (pad->pos (12, 0, 4) == 3);
  assert (pad->pos (pad->size ()) == pad->pos (pad->size () - 1));
  assert (pad->pos (pad->size () + 1) == pad->pos (pad->size () - 2));
  assert (pad->pos (2, 2) == 1);
  assert (pad->pos (-2, 2) == 1);
  assert (pad->pos (-1, 1, 2) == 1);

  assert (pad->pos (-6, 2, 4) == 2+2);
  assert (pad->pos (-5, 2, 4) == 2+3);
  assert (pad->pos (-4, 2, 4) == 2+3);
  assert (pad->pos (-3, 2, 4) == 2+2);
  assert (pad->pos (-2, 2, 4) == 2+1);
  assert (pad->pos (-1, 2, 4) == 2+0);
  assert (pad->pos (4, 2, 4) == 2+3);
  assert (pad->pos (5, 2, 4) == 2+2);
  assert (pad->pos (6, 2, 4) == 2+1);
  assert (pad->pos (7, 2, 4) == 2+0);
  assert (pad->pos (8, 2, 4) == 2+0);
  assert (pad->pos (9, 2, 4) == 2+1);
  assert (pad->pos (10, 2, 4) == 2+2);
  assert (pad->pos (11, 2, 4) == 2+3);
  assert (pad->pos (12, 2, 4) == 2+3);

  ((MirrorPosition*)pad)->setlaxis (false);
  ((MirrorPosition*)pad)->setraxis (true);

  cout << "false/true...\n   ";
  for (int i = -10; i < 15; i++)
    {
      if (i == 0 || i == 4)
        {
          cout << " |  ";
        }
      val = pad->pos (i, 2, 4, sign);
      
      cout << sign * val << ' ';
    }
  cout << endl;

  assert (pad->pos (-1) == 1);
  assert (pad->pos (-6, 0, 4) == 1);
  assert (pad->pos (-5, 0, 4) == 2);
  assert (pad->pos (-4, 0, 4) == 3);
  assert (pad->pos (-3, 0, 4) == 3);
  assert (pad->pos (-2, 0, 4) == 2);
  assert (pad->pos (-1, 0, 4) == 1);
  assert (pad->pos (4, 0, 4) == 3);
  assert (pad->pos (5, 0, 4) == 2);
  assert (pad->pos (6, 0, 4) == 1);
  assert (pad->pos (7, 0, 4) == 0);
  assert (pad->pos (8, 0, 4) == 1);
  assert (pad->pos (9, 0, 4) == 2);
  assert (pad->pos (10, 0, 4) == 3);
  assert (pad->pos (11, 0, 4) == 3);
  assert (pad->pos (12, 0, 4) == 2);

  assert (pad->pos (-6, 4, 4) == 4+1);
  assert (pad->pos (-5, 4, 4) == 4+2);
  assert (pad->pos (-4, 4, 4) == 4+3);
  assert (pad->pos (-3, 4, 4) == 4+3);
  assert (pad->pos (-2, 4, 4) == 4+2);
  assert (pad->pos (-1, 4, 4) == 4+1);
  assert (pad->pos (4, 4, 4) == 4+3);
  assert (pad->pos (5, 4, 4) == 4+2);
  assert (pad->pos (6, 4, 4) == 4+1);
  assert (pad->pos (7, 4, 4) == 4+0);
  assert (pad->pos (8, 4, 4) == 4+1);
  assert (pad->pos (9, 4, 4) == 4+2);
  assert (pad->pos (10, 4, 4) == 4+3);
  assert (pad->pos (11, 4, 4) == 4+3);
  assert (pad->pos (12, 4, 4) == 4+2);

  ((MirrorPosition*)pad)->setlaxis (true);
  ((MirrorPosition*)pad)->setraxis (false);

  cout << "true/false...\n  ";
  for (int i = -10; i < 15; i++)
    {
      if (i == 0 || i == 4)
        {
          cout << " |  ";
        }
      val = pad->pos (i, 2, 4, sign);
      
      cout << sign * val << ' ';
    }
  cout << endl;

  assert (pad->pos (-1) == 0);
  assert (pad->pos (-6, 0, 4) == 1);
  assert (pad->pos (-5, 0, 4) == 2);
  assert (pad->pos (-4, 0, 4) == 3);
  assert (pad->pos (-3, 0, 4) == 2);
  assert (pad->pos (-2, 0, 4) == 1);
  assert (pad->pos (-1, 0, 4) == 0);
  assert (pad->pos (4, 0, 4) == 2);
  assert (pad->pos (5, 0, 4) == 1);
  assert (pad->pos (6, 0, 4) == 0);
  assert (pad->pos (7, 0, 4) == 0);
  assert (pad->pos (8, 0, 4) == 1);
  assert (pad->pos (9, 0, 4) == 2);
  assert (pad->pos (10, 0, 4) == 3);
  assert (pad->pos (11, 0, 4) == 2);
  assert (pad->pos (12, 0, 4) == 1);

  assert (pad->pos (-6, 3, 4) == 3+1);
  assert (pad->pos (-5, 3, 4) == 3+2);
  assert (pad->pos (-4, 3, 4) == 3+3);
  assert (pad->pos (-3, 3, 4) == 3+2);
  assert (pad->pos (-2, 3, 4) == 3+1);
  assert (pad->pos (-1, 3, 4) == 3+0);
  assert (pad->pos (4, 3, 4) == 3+2);
  assert (pad->pos (5, 3, 4) == 3+1);
  assert (pad->pos (6, 3, 4) == 3+0);
  assert (pad->pos (7, 3, 4) == 3+0);
  assert (pad->pos (8, 3, 4) == 3+1);
  assert (pad->pos (9, 3, 4) == 3+2);
  assert (pad->pos (10, 3, 4) == 3+3);
  assert (pad->pos (11, 3, 4) == 3+2);
  assert (pad->pos (12, 3, 4) == 3+1);
  DELETE (pad);
  
  pad = NEW (PeriodicPosition (8));
  
  cout << "PeriodicPosition...\n";
  assert (pad->pos (-1) == 7);
  assert (pad->pos (pad->size ()) == 0);
  assert (pad->pos (pad->size () + 1) == 1);
  assert (pad->pos (2, 2) == 0);
  assert (pad->pos (-2, 2) == 0);
  assert (pad->pos (-1, 1, 2) == 2);

#if 0
#define S 5
  pad->size (S);
  
  int first = 2, last = 2 + S - 1;
  
  // extend left periodically
  while (first > 0) {
    first--;
    cout << "first: " << first << ", pos: " << first + S - 2 << endl;
  }
  while (last < 2*2 + S - 1) {
    last++;
    cout << "last : " << last << ", pos: " << last - S - 2 << endl;
  }

  cout << "-1: " << pad->pos (-1) << endl;
  cout << "-2: " << pad->pos (-2) << endl;
  cout << " " << S << ": " << pad->pos (S) << endl;
  cout << " " << S + 1 << ": " << pad->pos (S + 1) << endl;
#endif
  DELETE (pad);

  cout << "Test of class VectorPosition completed successfully.\n";
  return 0;
}
