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

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


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