// Hilbert class header file

#ifndef hilbert_h
#undef AFX_API
#define AFX_API AFX_EXT_CLASS
#define hilbert_h

#include <iostream.h>

#include "complex.h"
#include "bstate.h"
#include "cmodexp.h"

class CHilbert
{
	// overloaded operators
	friend ostream& operator <<(ostream&, CHilbert&);

private:

	int n_qbs;			// number of qubits in the Hilbert space
	int n_bs;			// number of basis states spanning the Hilbert space
	CComplex* stateamp;	// ptr to array of complex state amplitudes

public:

	// constructor (all complex amplitudes set to zero - explicitly)
	CHilbert(int);
	// constructor (second argument is initial value)
	CHilbert(int, int);
	
	// destructor
	~CHilbert();
	
	// accessor functions
	int numbits(void);		// return number of qubits in the Hilbert space
	int numbs(void);		// return number of basis states spanning the Hilbert space
	CComplex retamp(int);	// return the i'th complex amplitude
	
	// set function
	void setamp(int, CComplex);	// set the complex amplitude of the i'th 
								// basis
	// functions
	void normalise(void);		// normalise, i.e. ensure that the sum of
								// probabilities = 1
	void reverse(void);			// reverse the order of the basis states
								// e.g. camp @ |0001001> -> camp @ |1001000>
								// this is used after the qft as results are
								// presented in reverse
	CHilbert* subspaceprojection(int, int*);	// projects the entire space onto a subspace
												// defined by the qubit list
												// returns the subspace defined by the qubit list

	// measurement functions
	int measure(void);			// project entire space onto one basis state 
								// index of basis state returned
	int measure(int, int*, THREADPARAMS*);	// make a measurment on a subspace of the
											// the entire space defined by the qubit list
											// the space is then restricted to this value
	// modula exponentiation function application
	void modexp(int, int, int, int);	// calculate f(A) = X(xy)A mod N
										// |reg2 reg1> 
										// reg1 - A		(lower qubits)
										// reg2 - F(A)	(upper qubits)
										// takes values: num qubits in reg1, 
										// num qubits in reg2 (not used), X and N
								
	// copy operator
	CHilbert& operator =(CHilbert&);
};

#endif