// Basis state implementation file

#include <stdafx.h>

#include <math.h>
#include <stdlib.h>
#include <assert.h>

#include "bstate.h"

// constructors

CBstate::CBstate(int nqubits) 
{
	n_qbs = nqubits;

	state = new bool[n_qbs];	// will initialise to false
	assert(state != 0);			// ensure allocation

}

CBstate::CBstate(int nqubits, int index)
{
	n_qbs = nqubits;

	state = new bool[n_qbs];	// will initialise to false
	assert(state != 0);			// ensure allocation

	for(int i = nqubits-1; i >= 0; i--)	// set appropriate states
	{									// of qubits in basis state
		if(index >= pow(2,i)) 
		{
			state[i] = true;
			index -= (int)pow(2,i);
		}
		else
			state[i] = false;
	}
}

// destructor

CBstate::~CBstate()
{
	delete[] state;	// recover memory
}

// accessor functions

int CBstate::numbits(void)
{
	return n_qbs;
}

bool CBstate::retbool(int index)
{
	return state[index];
}

// set function

void CBstate::setbasis(int index)
{
	for(int i = n_qbs-1; i >= 0; i--)	// set the appropriate states	
	{									// of qubits in basis state
		if(index >= pow(2,i)) 
		{
			state[i] = true;
			index -= (int)pow(2,i);
		}
		else
			state[i] = false;
	}
}

// functions

int CBstate::indexnumber(void)
{
	int n = 0;
	for(int i = 0; i < n_qbs; i++)
	{
		if(state[i])
			n += (int)pow(2,i);
	}

	return n;
}

int CBstate::small_index(int b_d, int* qubits)
{
	// b_d represents the number of qubits in the smaller space
	// (basis dimensions)

	CBstate* smallstate = new CBstate(b_d);

	for(int i = 0; i < b_d; i++)
		smallstate->state[i] = state[qubits[i]];
	
	int n = 0;

	for(i = 0; i < b_d; i++)
	{
		if(smallstate->state[i])
			n += (int)pow(2,i);
	}

	delete smallstate;
	return n;
}

int CBstate::rev_index()
{
	CBstate* revstate = new CBstate(n_qbs);

	for(int j = 0; j < n_qbs; j++)
		revstate->state[j] = state[n_qbs-1-j]; 

	int revindex = revstate->indexnumber();

	delete revstate;
	return revindex;
}

ostream& operator <<(ostream& out, CBstate& bstate)
{
	out << "|";

	for(int i = bstate.numbits() - 1; i >= 0; i--)
	{
		out << bstate.retbool(i);
	}
	out << '>';

	return out;
}

CBstate* CBstate::concatenate(CBstate* b1, int* list1, CBstate* b2, int* list2)
{
	// this function is VERY scrappy, but since it isn't
	// actually used it isn't really a problem!

	int l1 = b1->n_qbs;
	int l2 = b2->n_qbs;

	int total_n = l1 + l2;

	int last_min = -1;

	int* biglist = new int[total_n];

	CBstate* bigstate = new CBstate(total_n);

	// form list of all qubits
	for(int i = 0; i < total_n; i++)
	{
		if(i < l1)
			biglist[i] = list1[i];
		else
			biglist[i] = list2[i - l1];
	}

	int pos;

	// set state bools for bigbasis
	for(i = 0; i < total_n; i++)
	{
		int current_min = 1000;

		for(int j = 0; j < total_n; j++)
		{
			if(biglist[j] < current_min && biglist[j] > last_min)
			{
				current_min = biglist[j];
				pos = j;
			}
		}

		if(pos < l1)
			bigstate->state[i] = b1->state[pos];
		else
			bigstate->state[i] = b2->state[pos - l1];

		last_min = biglist[pos];

	}

	return bigstate;
}

	

