//---------------------------------------------------------------------------
#include "QC_ccnot.h"
//---------------------------------------------------------------------------
/**
 * Constructor
**/
QC_ccnot::QC_ccnot(int _target, int _control1, int _control2) : QCalcUnit() {
    TargetBit = _target;
    ControlBit1 = _control1;
    ControlBit2 = _control2;
}
//---------------------------------------------------------------------------
/**
 *
**/
void
QC_ccnot::calc(int target, int control1, int control2,
               double R[], double I[], int NumberOfBits) {
// Sort Bits to reglar order of bit number
    int Bit0 = target;
    int Bit1 = control1;
    int Bit2 = control2;
    if (Bit0 > Bit1) swap(Bit0, Bit1);
    if (Bit1 > Bit2) swap(Bit1, Bit2);
    if (Bit0 > Bit1) swap(Bit0, Bit1);

    unsigned int states = 1 << (NumberOfBits - 3);

    for (unsigned int i = 0; i < states; i++) {
        unsigned int ix = i;
        ix = insert1(ix,Bit0);
        ix = insert1(ix,Bit1);
        ix = insert1(ix,Bit2);

        unsigned int ix_1 = ix;
        unsigned int ix_0 = ix & ~(1 << target); //Set TargetBit 0
        swap(R[ix_0], R[ix_1]);
        swap(I[ix_0], I[ix_1]);
    }

}
//---------------------------------------------------------------------------
void
QC_ccnot::Calc(QBits *qBits) {
    double *R = qBits->GetBitsR();//Real Part
    double *I = qBits->GetBitsI();//Imaginary Part
    int N = qBits->GetNumberOfQBits();

    QC_ccnot::calc(TargetBit, ControlBit1, ControlBit2, R, I, N);
}
//---------------------------------------------------------------------------
#ifdef __USE__MPI
void
QC_ccnot::calcmpi(int t1, int c1, int c2, double R[], double I[], int N) {

    // Sort Bits to reglar order of bit number
    int Bit0 = t1;
    int Bit1 = c1;
    int Bit2 = c2;
    if (Bit0 > Bit1) {
        swap(Bit0, Bit1);
    }
    if (Bit1 > Bit2) {
        swap(Bit1, Bit2);
    }
    if (Bit0 > Bit1) {
        swap(Bit0, Bit1);
    }

    double r0 = 0.0;
    double i0 = 0.0;
    double r1 = 0.0;
    double i1 = 0.0;
    unsigned int ix0, ix1;

    for (int i = 0; i < (1 << (N - 3)); i++) {
        unsigned int ix = i;
        ix = insert1(ix,Bit0);
        ix = insert1(ix,Bit1);
        ix = insert1(ix,Bit2);
        unsigned int ix_1 = ix;
        unsigned int ix_0 = ix & ~(1 << t1); //Set TargetBit 0
        bool bstore = setup(R, I, ix0, ix1, r0, i0, r1, i1);
        if (bstore) {
            swap(r0, r1);
            swap(i0, i1);
            // Store:
            store(R, I, ix0, ix1, r0, i0, r1, i1);
        }
    }
}
#endif
//---------------------------------------------------------------------------
