// Lemur OLAP library (c) 2003 National Research Council of Canada by Daniel Lemire, and Owen Kaser
 /**
 *  This program is free software; you can
 *  redistribute it and/or modify it under the terms of the GNU General Public
 *  License as published by the Free Software Foundation (version 2). This
 *  program is distributed in the hope that it will be useful, but WITHOUT ANY
 *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 *  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 *  details. You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software Foundation,
 *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
#include "../lemurcore/common.h"
#include "../lemurcore/datacube.h"
#include "../lemurcore/chunkeddatacube.h"

/**
* Test to see if chunkeddatacube is sane for 2D cubes.
*/
void test2D() {
  vector<int> shape(2,5);
  vector<int> chunk(2,2);
  ChunkedDataCube<int,int> dc(shape, chunk);
  dc.open();
  //dc.fillWithZeroes(); // no longer needed
  // just some initial tests...
  cout << "checking position (4,0)"<< endl;
  vector<int> pos (2,0);
  pos[0] = 4; pos[1] = 0;
  dc.getChunkIndex(pos);
  cout << "done checking position (4.0)"<< endl;
  for(int row = 0; row < 5; ++row) {
    for(int col = 0; col < 5; ++col) {
      vector<int> pos (2,0);
      pos[0] = row; pos[1] = col;
      cout << dc.getChunkIndex(pos) << " ";
    }
    cout << endl;
  }
  for(int row = 0; row < 5; ++row) {
    for(int col = 0; col < 5; ++col) {
      vector<int> pos (2,0);
      pos[0] = row; pos[1] = col;
      cout << dc.getIndexInChunk(pos) << " ";
    }
    cout << endl;
  }
  vector<bool> allocated(5*5,false);
  for(int row = 0; row < 5; ++row) {
    for(int col = 0; col < 5; ++col) {
      vector<int> pos (2,0);
      pos[0] = row; pos[1] = col;
      assert(!allocated[dc.getIndexInChunk(pos)+dc.getChunkIndex(pos)]);
      allocated[dc.getIndexInChunk(pos)+dc.getChunkIndex(pos)] = true;
    }
  }
  dc.close();
}

/**
* Test to see if chunkeddatacube is sane for 3D cubes.
*/
void test3D() {
  int X = 5, Y = 7, Z = 9;
  vector<int> shape(3);
  shape[0] = X;
  shape[1] = Y;
  shape[2] = Z;
  vector<int> chunk(3,2);
  ChunkedDataCube<int,int> dc(shape, chunk);
  dc.open();
  //dc.fillWithZeroes(); // no longer needed
  for(int x = 0; x < X; ++x) {
    for(int y = 0; y < Y; ++y) {
      for(int z = 0; z < Z; ++z) {
        vector<int> pos (3,0);
        pos[0] = x; pos[1] = y;pos[2] = z;
        cout << dc.getChunkIndex(pos) << " ";
      }
      cout << endl;
    }
    cout << endl;
  }
  for(int x = 0; x < X; ++x) {
    for(int y = 0; y < Y; ++y) {
      for(int z = 0; z < Z; ++z) {
        vector<int> pos (3,0);
        pos[0] = x; pos[1] = y;pos[2] = z;
        cout << dc.getIndexInChunk(pos) << " ";
      }
      cout << endl;
    }
    cout << endl;
  }
  vector<bool> allocated(X*Y*Z,false);
  for(int x = 0; x < X; ++x) {
    for(int y = 0; y < Y; ++y) {
      for(int z = 0; z < Z; ++z) {
        vector<int> pos (3,0);
        pos[0] = x; pos[1] = y;pos[2] = z;
        assert(!allocated[dc.getIndexInChunk(pos)+dc.getChunkIndex(pos)]);
        allocated[dc.getIndexInChunk(pos)+dc.getChunkIndex(pos)] = true;
      }
    }
  }
  dc.close();
}

int main() {
  cout << "Testing ChunkedDataCube!" << endl;
  cout << "testing 2D" << endl;
  test2D();
  cout << "testing 3D" << endl;
  test3D();
  cout << "if you made it that far, you are probably ok." << endl;
  return 0;
}


