// dynamic_alocation_of_memory_malloc.cpp
//
#ifdef _WIN32
	#include <tchar.h>
	#include <conio.h>
#elif (defined __linux__) || (defined _AIX) || (defined __APPLE__)
	typedef char _TCHAR;
	#define _tmain main
#endif

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;

void my_getch();
void VynasobMatice(const unsigned, const unsigned, const unsigned, long double**,
	long double**,	long double**);
void VypisMaticu(const unsigned, const unsigned, long double**);

int _tmain(int argc, _TCHAR* argv[])
{
	//Deklarujeme A ako pointer na pointre na premenne typu long double
	long double** A, ** B, ** C;
	unsigned m, n, r, s, i, j;

	cout << "\n  Z klavesnice nacitajte matice A a B a vypiste ich na obrazovku" 
		<< " spolu\ns maticou A*B.\n\n";
	cout << "  Zadajte rad matice A!\n";
	cout << "  Pocet riadkov je ";
	cin >> m;
	cout << "  Pocet stlpcov je ";
	cin >> n;

	//Alokujeme dynamicke pole pre m pointrov na riadky matice (m = pocet riadkov)
	if ((A = (long double**)malloc(m * sizeof(long double*))) == NULL) {
		cout << "Nie je volna pamat!";
		exit(1);
	}

	cout << "\n  Zadajte prvky matice A!\n";
	for (i = 0; i < m; i++) {
		//Alokujeme dynamicke pole pre n prvkov m-teho riadu matice A 
		//(n = pocet stlpcov)
		if ((A[i] = (long double*)malloc(n * sizeof(long double))) == NULL) {
			cout << "Nie je volna pamat!";
			exit(1);
		}

		for (j = 0; j < n; j++) {
			cout << "    ";
			cout << "A[" << i << "][" << j << "]=";
			cin >> A[i][j];
		}
	}

	cout << endl << "  Zadajte rad matice B!\n";
	r = n;
	//r je pocet riadkov
	cout << "  Pocet stlpcov je ";
	cin >> s;
	if ((B = (long double**)malloc(r * sizeof(long double*))) == NULL) {
		cout << "Nie je volna pamat!";
		exit(1);
	}

	cout << "\n  Zadajte prvky matice B!\n";
	for (i = 0; i < r; i++) {
		if ((B[i] = (long double*)malloc(s * sizeof(long double))) == NULL) {
			cout << "Nie je volna pamat!";
			exit(1);
		}

		for (j = 0; j < s; j++) {
			cout << "    ";
			cout << "B[" << i << "][" << j << "]=";
			cin >> *(*(B + i) + j);
		}
	}

	if ((C = (long double**)malloc(m * sizeof(long double*))) == NULL) {
		cout << "Nie je volna pamat!";
		exit(1);
	}

	for (i = 0; i < m; i++)
		if ((C[i] = (long double*)malloc(s * sizeof(long double))) == NULL) {
			cout << "Nie je volna pamat!";
			exit(1);
		}

	VynasobMatice(m, n, s, A, B, C);

	cout << "\n  Zadali ste nasledujuce matice:\n\n";
	VypisMaticu(m, n, A);
	VypisMaticu(r, s, B);
	cout << "  Ich sucin je:\n\n";
	VypisMaticu(m, s, C);

	//Uvolnujeme pamat od vsetkych dynamickych premennych
	for (i = 0; i < m; i++) {
		free(A[i]);
		free(C[i]);
	}
	for (i = 0; i < r; i++)
		free(B[i]);
	free(A);
	free(B);
	free(C);

	my_getch();
	return 0;
}

void my_getch()
{
#ifdef _WIN32
	_getch();
#else
	//	cout << endl;
#endif
}

//Vystupnu dynamicky alokovanu premennu Z volate sposobom "by dereference"
void VynasobMatice(const unsigned m, const unsigned n, const unsigned s, 
	long double** X, long double** Y, long double** Z)
{
	long double Suma;

	for (unsigned i = 0; i < m; i++)
		for (unsigned j = 0; j < s; j++) {
			Suma = 0;
			for (unsigned k = 0; k < n; k++)
				Suma += X[i][k] * Y[k][j];
			Z[i][j] = Suma;
		}
}

void VypisMaticu(const unsigned m, const unsigned n, long double** X)
{
	for (unsigned i = 0; i < m; i++) {
		for (unsigned j = 0; j < n; j++)
			printf("%12.6Lf", X[i][j]);
		cout << "\n";
	}
	cout << "\n";
}