// 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.
 */
#ifndef NORMALUTIL_H
#define NORMALUTIL_H


#include "normalizationscommon.h"

#include "permutationutil.h"





// put everything that has to do with normalizing cubes irrespective of a
// a chunk geometry
template <class _DT, class _LDT>
class NormalUtil {
public:

    // display a nomrmalization
    static void dumpNorm(  norm_type &Norm) {
        cout << "normalization is " << endl;
        for (uint dim=0; dim < Norm.size(); ++dim) {
            vector<int>& norm = Norm[dim];
            for (uint j=0; j < norm.size(); j++) cout << norm[j] << " ";
            cout << endl;
        }
    }

    // copy a datacube to another using a given normalization
    static void copyTo(DataCube<_DT,_LDT> & source,DataCube<_DT,_LDT> & target,\
                       const norm_type& Normalization);

    // convenience method? see printSmall2d
    static void printSmall2d(DataCube<_DT,_LDT> & DC,
                             const norm_type& Normalization,
                             int m) {
        vector<int> cs(Normalization.size(),m);
        printSmall2d(DC,Normalization,cs);
    }

    // this must print a small 2d data cube
    static void printSmall2d(DataCube<_DT,_LDT> & DC,
                             const norm_type& Normalization,
                             const vector<int>& ChunkShape) {
        vector<int> shape = DC.getShape();
        vector<int> shapeToPrint(shape);
        if (shape.size() != 2) return;
        if (shape[0] > 100) {
            cout << "printing only x=0..99" << endl;
            shapeToPrint[0] = 100;
        }
        if (shape[1] > 100) {
            cout << "printing only y=0..99" << endl;
            shapeToPrint[1] = 100;
        }

        vector<int> Indices(2), newIndices(2);

        for (int y=0; y <= shapeToPrint[1]; ++y) {
            if ( y % ChunkShape[1] == 0 || y == shapeToPrint[1] ) {
                for (int z =0; z < shapeToPrint[0]; ++z) {
                    if (z % ChunkShape[0] == 0) cout << "+";
                    cout << "-";
                }
                cout << "+" << endl;
            }
            if (y == shapeToPrint[1]) return;

            for (int x=0; x < shapeToPrint[0]; ++x) {
                if (x % ChunkShape[0] == 0) cout << "|";
                // since efficiency does not matter, don't bother with varargs etc
                Indices[0] = x; Indices[1] = y;
                newIndices = PermutationUtil::permute(Indices,Normalization);
                cout << (DC.get(newIndices) != 0 ? "*" : " ");
            }
            cout << "|" << endl;
        }
    }






};

template <class _DT, class _LDT>
void NormalUtil<_DT,_LDT>::copyTo(DataCube<_DT,_LDT> & source,\
                                  DataCube<_DT,_LDT> & target,\
                                  const norm_type& Normalization) {
    vector<int> Shape = source.getShape();
    //
    //
    vector<int> Indices(source.getShape().size(),0);
    vector<int> Start(source.getShape().size(),0);
    //
    vector<int> newIndices = PermutationUtil::permute(Indices,Normalization);
    target.put( source.get(newIndices) , Indices );
    //
    while(MathUtil::increment( Indices, Start, Shape)) {
        vector<int> newIndices = PermutationUtil::permute(Indices,Normalization);
        target.put( source.get(newIndices) , Indices );
    }

}




#endif

