#include <iostream>
#include <vector>
using namespace std;

//desetichno -> dvoichno

vector<bool> DtoB(int val) {
	vector<bool> binary;
	bool negative = val < 0;

	while (val != 0) {
		binary.push_back(val % 2);
		val /= 2;
	}
	binary.push_back(negative);

	return binary;
}

//dvoichno -> desetichno

int BtoD() {
	//lol nishto
	return 0;
}

class Register {
	int n; //razrqd
	vector<bool> reg; //stoinost
	bool V; //prepulvane

public:
	//Constructors

	Register(int nBits) {
		this->n = nBits;
		this->reg.assign(this->n, 0);
		this->V = 0;
	}

	Register(int nBits, int val) {
		this->n = nBits;
		this->reg.assign(this->n, 0);
		vector<bool> value = DtoB(val);

		if (n <= value.size()) {
			for (int i = 0; i < n; i++) {
				reg[i] = value[i];
			}
		}
		else {
			for (int i = 0; i < value.size() - 1; i++) {
				reg[i] = value[i];
			}
			reg[n - 1] = value[value.size() - 1];
		}

		this->V = 0;
	}

	//Setters, getters

	bool getV() const{
		return V;
	}

	void setV(bool v) {
		this->V = v;
	}

	vector<bool> getReg() const {
		return reg;
	}

	void setReg(vector<bool> binary) {
		if (n <= binary.size()) {
			for (int i = 0; i < n; i++) {
				reg[i] = binary[i];
			}
		}
		else {
			for (int i = 0; i < binary.size(); i++) {
				reg[i] = binary[i];
			}
		}
		this->V = 0;
	}

	int getN() const {
		return n;
	}

	//output

	void print(char divider = ' ') const{
		cout << reg[n - 1] << '|';
		for (int i = n - 2; i >= 0; i--) {
			cout << reg[i];
		}
		cout << divider;
	}

	void print(int start, int end, char divider = ' ') const {
		cout << reg[end] << '|';
		for (int i = end - 1; i >= start; i--) {
			cout << reg[i];
		}
		cout << divider;
	}

	void printDouble(char divider = ' ') const {
		int half = n / 2;
		cout << reg[n - 1] << '|';
		for (int i = n - 2; i >= half; i--) {
			cout << reg[i];
		}
		cout << ' ';
		for (int i = half - 1; i >= 0; i--) {
			cout << reg[i];
		}
		cout << divider;
	}

	//operatori

	std::vector<bool>::reference operator [] (unsigned int i){
		return reg[i];
	}
	
	bool operator [] (unsigned int i) const{
		return reg[i];
	}

	void operator << (int s) {
		for (int i = n - 1; i >= s; i--) {
			reg[i] = reg[i - s];
		}
		for (int i = 0; i < s; i++) {
			reg[i] = 0;
		}
	}

	void operator >> (int s) {
		for (int i = 0; i < n - s; i++) {
			reg[i] = reg[i + s];
		}
		for (int i = n - 1; i >= n - s; i--) {
			reg[i] = 0;
		}
	}

	Register operator + (const Register& b) const {
		Register result(n);
		bool carry = 0;

		for (int i = 0; i < this->n; i++) {
			result[i] = (reg[i] != b[i]) != carry;
			carry = (reg[i] && b[i]) || ((reg[i] || b[i]) && carry);
		}

		//prepulvane
		result.V = (reg[n - 1] && b[n - 1] && !result[n - 1])
					|| (!reg[n - 1] && !b[n - 1] && result[n - 1]);

		return result;
	}

	void operator ++ () {
		int i;
		for (i = 0; i < n; i++) {
			if (reg[i] == 0) {
				reg[i] = 1;
				break;
			}
			else {
				reg[i] = 0;
			}
		}
		if (i == n - 1 && reg[i] == 1) {
			this->V = 1; // prepulvane
		}
	}

	//funkcii za preobrazuvane

	void convertDK() {
		for (int i = 0; i < n - 1; i++) {
			reg[i] = !reg[i];
		}
		++*(this);
	}

	void negate() {
		reg[n - 1] = !reg[n - 1];
		for (int i = 0; i < n - 1; i++) {
			reg[i] = !reg[i];
		}
		++ *(this);
	}
};

void multiply(Register& x, Register& y) {
	
	int n = y.getN();
	int last = n * 2 - 1;
	Register Mn(n * 2);
	Register sum(n * 2);

	Mn.setReg(x.getReg());
	Mn << n;
	sum.setReg(y.getReg());

	//output
	cout << "Mn:   "; Mn.print(n, last, '\n');
	cout << "Z:    "; sum.printDouble(); cout << "Mt" << endl;

	int i;
	for (int i = 1; i < n; i++) {

		if (sum[0] == 1) {
			sum = sum + Mn;

			//output
			cout << "     + |" << endl;
			cout << "Mn:   "; Mn.print(n, last, '\n');
			cout << "------------------------" << endl;
			cout << "Z:    ";  sum.printDouble('\n');
		}


		bool V = sum.getV();
		bool c = sum[last];
		bool sign = (c && !V) || (!c && V);
		sum >> 1;
		sum[last] = sign;
		sum.setV(0);

		//output
		cout << "-->   "; sum.printDouble();
		cout << ' ' << i << ") S = (" << c << " * " << !V << ") + (" << !c << " * " << V << ") = " << sign;
		cout << endl;
	}

	if (sum[0] == 1) {
		
		Mn.negate();
		sum = sum + Mn;

		//output
		cout << "     + |" << endl;
		cout << "-Mn:  "; Mn.print(n, last, '\n');
		cout << "------------------------" << endl;
		cout << "Z:    ";  sum.printDouble('\n');
	}
	bool V = sum.getV();
	bool c = sum[last];
	bool sign = (c && !V) || (!c && V);
	sum >> 1;
	sum[last] = sign;
	sum.setV(0);

	//output
	cout << "-->   "; sum.printDouble();
	cout << ' ' << n << ") S = (" << c << " * " << !V << ") + (" << !c << " * " << V << ") = " << sign;
	cout << endl << endl;
	cout << "Z = "; sum.printDouble('\n');

}

int main() {
	Register regA(8, 56);
	Register regB(8, -27);
	regB.convertDK();
	Register regC(8);
	Register regD(8, -128);
	regD.convertDK();
	Register regE(8, -1);
	regB.convertDK();

	multiply(regA, regB);


	//++regC;
	//regC.print();
	//++regC;
	//regC.print();
	//++regC;
	//regC.print();

	//regD.print();
	//regD.convertDK();
	//regD.print();
	//++regD;
	//regD.print();

	//regE.print();
	//regE.convertDK();
	//regE.print();
	//++regE;
	//regE.print();
}