#ifndef TENSOR2D_CPP
#define TENSOR2D_CPP
#include <iostream>
#include <utility>
#include "tensor2D.h"

template<typename T>
Tensor2D<T>::Tensor2D(int rows, int columns):r(rows),c(columns) {
	data=new T*[r];
	for(int i=0;i<r;i++){
		data[i]=new T[c];
		for(int j=0; j<c; j++) {
			data[i][j]=T();
		}
	}
}

template<typename T>
Tensor2D<T>::Tensor2D(const Tensor2D<T>& other):r(other.r),c(other.c) {
	data=new T*[r];
	for(int i=0;i<r;i++){
		data[i]=new T[c];
		for(int j=0; j<c; j++) {
			data[i][j]=other.data[i][j];
		}
	}
}

template<typename T>
Tensor2D<T>& Tensor2D<T>::operator=(const Tensor2D<T>& other){
	if(this==&other)
		return *this;
	for(int i=0; i<r; i++) {
		delete[] data[i];
	}
	delete[] data;
	r=other.r;
	c=other.c;
	data=new T*[r];
	for(int i=0;i<r;i++){
		data[i]=new T[c];
		for(int j=0;j<c;j++) {
			data[i][j]=other.data[i][j];	
		}
	}
}
template<typename T>
Tensor2D<T>::~Tensor2D() {
	for(int i=0; i<r; i++) {
		delete[] data[i];
	}
	delete[] data;
}

template<typename T>
void Tensor2D<T>::set(int row, int col, T& value) {
	data[row][col]=value;
}

template<typename T>
T Tensor2D<T>::get(int row, int col) const {
	return data[row][col];
}

template<typename T>
T& Tensor2D<T>::operator()(int row, int col) {
	return data[row][col];
}

template<typename T>
T& Tensor2D<T>::operator()(int row, int col) const {
	return data[row][col];
}

template<typename T>
T* Tensor2D<T>::operator[](int row) {
	return data[row];
}

template<typename T>
T* Tensor2D<T>::operator[](int row) const {
	return data[row];
}

template<typename T>
std::pair<int,int> Tensor2D<T>::shape()const {
	return {r,c};
}

template<typename T>
int Tensor2D<T>::rows() const {return r;}

template<typename T>
int Tensor2D<T>::cols() const {return c;}

template<typename T>
void Tensor2D<T>::print(void) {
	for(int i=0; i<r; i++) {
		for(int j=0;j<c;j++){
			std::cout<<data[i][j]<<"\t";
		}
		std::cout<<std::endl;		
	}
}
/*Explicit template instantiations use*/

template class Tensor2D<int>;
template class Tensor2D<double>;
template class Tensor2D<float>;
#endif
