#include "Matrix.h"
#include <exception>
using namespace std;


Matrix::Matrix(int nrLines, int nrColumns) {
	// Theta(1)
	if (nrLines <= 0 || nrColumns <= 0) {
		throw exception();
	}
	this->numberOfLines = nrLines;
	this->numberOfColumns = nrColumns;
	this->values = new TElem[nrLines * nrColumns];
	this->lines = new int[nrLines * nrColumns];
	this->columns = new int[nrColumns+1];
	for (int i = 0; i < nrColumns+1; i++) {
		this->columns[i] = 0;
	}
	   
}


int Matrix::nrLines() const {
	// Theta(1)
	return this->numberOfLines;
}


int Matrix::nrColumns() const {
	// Theta(1)
	return this->numberOfColumns;
}


TElem Matrix::element(int i, int j) const {
	// Best: theta(1) | Worst: theta( nr of non-zero elements in the column) | Total: theta( nr of non-zero elements in the column)

	if(i>=this->numberOfLines || j>=this->numberOfColumns || i<0 || j<0)
		throw exception();
	
	for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
		if(this->lines[k+this->columns[j]]==i)
			return this->values[k+this->columns[j]];
	}
	return NULL_TELEM;
}

TElem Matrix::modify(int i, int j, TElem e) {
	// Best: theta(1) | Worst: theta( nr of rows + nr of non zero values + nr of non zero values in the column) | Total: theta( nr of rows + nr of non zero values + nr of non zero values in the column)

	if(i>=this->numberOfLines || j>=this->numberOfColumns  || i<0 || j<0)
		throw exception();
	
	for(int k=0;k<this->columns[j+1]-this->columns[j];k++){
		if(this->lines[k+this->columns[j]]==i){
			swap(this->values[k+this->columns[j]],e);
			return e;
		}
	}
	for(int k=this->columns[this->numberOfColumns];k>this->columns[j];k--){
		swap(this->lines[k],this->lines[k-1]);
		swap(this->values[k],this->values[k-1]);
	}
	this->lines[this->columns[j]]=i;
	this->values[this->columns[j]]=e;
	for(int k=j+1;k<=this->numberOfColumns;k++)
		this->columns[k]++;
	return NULL_TELEM;
}

void Matrix::setMainDiagonal(TElem e) {
	// Theta(min(nr of rows,nr of cols))
	int length = this->numberOfLines;
	if (this->numberOfColumns < this->numberOfLines) {
		length = this->numberOfColumns;
	}
	for (int i = 0; i < length; i++) {
		this->modify(i, i, e);
	}
}

