//---------------------------------------------------------------------------
//  Calc unit
//---------------------------------------------------------------------------
#ifndef QCalcUnitH
#define QCalcUnitH
//---------------------------------------------------------------------------
#include <string>
#include <sstream>

#ifdef __USE__MPI
#include <mpi.h>
#endif //__USE__MPI

#include "QBits.h"
//---------------------------------------------------------------------------
class QCalcUnit
{
protected :
//---
// for MPI
//---
#ifdef __USE__MPI
    static int gMdata;  // the number of the states which each process treats
    static int gNqubits;
    static int gProcMask;
    static int gProcBit;
    static int gMyID;
    static int gNumprocs;
#endif //__USE__MPI


public:
    virtual void Calc(QBits *qBits) = 0;
    virtual std::string GetName(void) const = 0;
    static unsigned int insert0(unsigned int i0, unsigned int BitNum);
    static unsigned int insert1(unsigned int i0, unsigned int BitNum);
    static void swap(double &x,double &y) {
        double tmp = x;
        x = y;
        y = tmp;
    };
    static void swap(int    &x,int    &y) {
        int    tmp = x;
        x = y;
        y = tmp;
    };

//---
// for MPI
//---

    static inline int getOriginalID(int id);
    static inline int getProcFromID(int id);
    static bool setup(const double R[], const double I[],
                      const unsigned int &ix0, const unsigned int &ix1,
                      double &r0, double &i0,
                      double &r1, double &i1);
    static void store(double R[], double I[],
                      const unsigned int &ix0, const unsigned int &ix1,
                      const double &r0, const double &i0,
                      const double &r1, const double &i1);
    static void showdata(double R[], double I[]);

    static int initmpi(int N, int myid, int numprocs);
    static void initdata(double R[], double I[]);

};
//---------------------------------------------------------------------------
#endif //QCalcUnitH
