#include <iostream>
#include "tensor2D.hpp"

template<typename T>
Tensor2D<T>::Tensor2D(int rows,int cols) {
	r=rows;
	c=cols;
	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 &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 &other){
	if (this==&other)
		return *this;
	delete [] data;
	r=other.r;
	c=other.c;
	data=new T*[r];
	for(int i=0;i<r;i++){
		for(int j=0;j<c;j++){
			data[i][j]=other.data[i][j];
		}
	}
	return *this;
}

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;c++){
			std::cout<<data[i][j]<<" ";
		}
		std::cout<<std::endl;
	}
}

/*Explicit template instations use*/
template class Tensor2D<int>;
template class Tensor2D<double>;
template class Tensor2D<float>;
