#include <stdio.h>
#include <iostream>
#include <cmath>

using namespace std;

/* zu Aufgabe 4a.1:
Beschreibung:

Funktion zur Umwandlung einer dezimalen Zahl
in bin�re Darstellung.

�bergabearameter:

dez_zahl	- die zu umwandelnde Dezimalzahl,
bitanzahl	- Anzahl der Bits in bin�rer Darstellung.
bit_vektor	- Ergebnisarray aus den Bitstellen der bin�ren Zahl.

*/
void dez_to_bin(int bit_vektor[], int dez_zahl, int bitanzahl)

{
	// *******************************************************************************
	// Die Funktion mit dem Inhalt f�llen

		if (dez_zahl < 0){
				dez_zahl = std::pow(2, bitanzahl) + dez_zahl;
		}
		for(int i = 0; i < bitanzahl; i++){
			bit_vektor[i] = dez_zahl % 2; //BigEndian (Most Significant Bit (MSB) at the end)
			dez_zahl /= 2;
		}
    /*Hier in LittleEndian
		for(int i = 0; i < bitanzahl; i++){
			bit_vektor[bitanzahl - i - 1] = dez_zahl % 2; //LittleEndian (Least Significant Bit (MSB) at the end)
			dez_zahl /= 2;
		}
		*/
}

void halb_add(int ergebnis[], int bin_zahl1[], int bin_zahl2[], bool sum_carry)
{

	if (sum_carry)
	{

		// f�r Summe
		for (int i = 0; i <= 31; i++)
		{

			ergebnis[i] = (bin_zahl1[i] ^ bin_zahl2[i]);
		}
	}

	else
	{

		//f�r carry
		for (int i = 0; i <= 31; i++)
		{

			ergebnis[i] = (bin_zahl1[i] & bin_zahl2[i]);

		}
	}
}

// Alternativ 1-Bit-Halbaddierer
int halb_add_1bit(int bin_zahl1, int bin_zahl2, bool sum_carry)
{

	if (sum_carry)
	{


		return	(bin_zahl1 ^ bin_zahl2);
	}


	else
	{

		//f�r carry

		return (bin_zahl1 & bin_zahl2);

	}
}
/* zu Aufgabe 4a.2:
Beschreibung:

Gibt den Vektor auf den Bildschirm aus.
(Wertigkeit der Bitstellen beachten!)

�bergabeparameter:

binzahl		- Feld, der ausgegeben wird,
anzahl_bits	- Anzahl der Bitstellen

*/

void ausgabe(int binzahl[], int anzahl_bits)
{
	// *******************************************************************************
	// Diesen Bereich bitte mit geeigneter Funktionalit�t f�llen
	//iterieren über int array und ausgeben der einzelnen Stellen
	for(int i = 0; i < anzahl_bits; i++){
		//print backwards 'cause binzahl is BigEndian and LittleEndian should be displayed
		cout << binzahl[anzahl_bits - 1 - i];
	}

	// *******************************************************************************
	cout << endl;
}


/* zu Aufgabe 4b.1:
Beschreibung:

Funktion beschreibt einen Volladdierer durch logische Gleichungen
f�r Summe und �bertag.

�bergabeparameter:

bin_zahl1	- die zu addierende Bin�rzahl (als Feld),
bin_zahl2	- die zu addierende Bin�rzahl (als Feld),
sum_carry	- Je nach Auswahl Berechnung der Summe oder des �bertrags.
ergebnis	- Ergebnisarray aus den Bitstellen der Summe / des �bertrags.

*/
void voll_add(int ergebnis[], int bin_zahl1[], int bin_zahl2[], bool sum_carry, int anzahl_bits)
{
	//check for valid bit number
	if (anzahl_bits > 32 || anzahl_bits < 1){
		cerr << "unexpected number of bits" << endl;
		return;
	}
	int c = 0;
	if(sum_carry){
		for(int i = 0; i < anzahl_bits ; i++){
			ergebnis[i] = ((bin_zahl1[i] ^ bin_zahl2[i]) ^ c); // c is carry
			c = ((bin_zahl1[i] & bin_zahl2[i]) | (bin_zahl1[i] & c)) | (bin_zahl2[i] & c);
		}
	}else
	{
		for(int i = 0; i < anzahl_bits ; i++){
			c = ((bin_zahl1[i] & bin_zahl2[i]) | (bin_zahl1[i] & c)) | (bin_zahl2[i] & c);
			ergebnis[i] = c;
		}
	}
}

int main()

{
	int dez_zahl1, dez_zahl2, anzahl_bits;

	int bin_zahl1[32] = { 0 };
	int bin_zahl2[32] = { 0 };
	int summe[32] = { 0 };
	int carry[33] = { 0 };

	cout << "Geben Sie 2 dezimale Zahlen ein:" << endl;
	cin >> dez_zahl1 >> dez_zahl2;
	cout << endl;

	cout << "Geben Sie Anzahl der Bits fuer binaere Darstellung ein:" << endl;
	cin >> anzahl_bits;

	// Konvertierung in Bin�rdarstellung
	dez_to_bin(bin_zahl1, dez_zahl1, anzahl_bits);
	dez_to_bin(bin_zahl2, dez_zahl2, anzahl_bits);

	// Ergebnisse f�r Halbaddierer
	cout << "\n\n========Halbaddierer========" << endl;

	cout << " ";
	ausgabe(bin_zahl1, anzahl_bits);
	cout << "+";
	ausgabe(bin_zahl2, anzahl_bits);
	cout << "______________________" << endl;

	halb_add(summe, bin_zahl1, bin_zahl2, true);
	halb_add(carry, bin_zahl1, bin_zahl2, false);

	ausgabe(carry, anzahl_bits);
	cout << " ";
	ausgabe(summe, anzahl_bits);
	cout << endl;

	cout << "========Halbaddierer========" << endl;

	// Ergebnisse f�r Volladdierer
	cout << "\n\n========Volladdierer========" << endl;

	cout << " ";
	ausgabe(bin_zahl1, anzahl_bits);
	cout << "+";
	ausgabe(bin_zahl2, anzahl_bits);
	cout << "______________________" << endl;


	voll_add(summe, bin_zahl1, bin_zahl2, true, anzahl_bits);
	voll_add(carry, bin_zahl1, bin_zahl2, false, anzahl_bits);

	ausgabe(carry, anzahl_bits);
	cout << " ";
	ausgabe(summe, anzahl_bits);
	cout << endl;

	system("pause");
	return 0;
}