diff --git a/data/tensor_01 b/data/tensor_01 new file mode 100644 index 0000000000000000000000000000000000000000..bab5500cfb84f2263f143b3dcda736bff38e523e --- /dev/null +++ b/data/tensor_01 @@ -0,0 +1,7 @@ +2 +2 +2 +1 +0 +0 +-1 \ No newline at end of file diff --git a/data/tensor_02 b/data/tensor_02 new file mode 100644 index 0000000000000000000000000000000000000000..698a8b66c5c48c890b0f4e8d8abc73beca2719e8 --- /dev/null +++ b/data/tensor_02 @@ -0,0 +1,12 @@ +3 +2 +2 +2 +1 +2 +3 +4 +5 +6 +7 +8 \ No newline at end of file diff --git a/tensor b/tensor new file mode 100755 index 0000000000000000000000000000000000000000..d83f8d9f8cffdd66e15c46e259e57f42b41cb183 Binary files /dev/null and b/tensor differ diff --git a/tensor.cpp b/tensor.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c652d4c1c4d2d70377c8feceac2c24504bc98b53 --- /dev/null +++ b/tensor.cpp @@ -0,0 +1,281 @@ +#include<iostream> +#include<vector> +#include<concepts> +#include<algorithm> +#include<utility> +#include<fstream> + +template< class T > +concept Arithmetic = std::is_arithmetic_v< T >; + +template<Arithmetic T> +class Tensor{ + public: + + //default constructor + Tensor() = default; + + //constructor with shape + Tensor(const std::vector< size_t >& shape){ + int numEle = numberElementsInShape(shape); + setTensorShape(shape); + vec.clear(); + for(int i =0; i<numEle;i++){ + vec.push_back(0); + } + } + + //contructor with fill value + Tensor(const std::vector< int >& shape, int& fillValue){ + int numEle = numberElementsInShape(shape); + setTensorShape(shape); + vec.clear(); + for(int i =0; i<numEle;i++){ + vec.push_back(fillValue); + } + } + + + //Copy constructor + Tensor(const Tensor<T>& copy_tensor){ + + std::copy(copy_tensor.vec.begin(), copy_tensor.vec.end(),std::back_inserter(vec)); + std::copy(copy_tensor.tensor_shape.begin(),copy_tensor.tensor_shape.end(),std::back_inserter(tensor_shape)); + rank = copy_tensor.rank; + } + + //Copy assignment operator + Tensor& operator=(const Tensor<T>& copy_tensor){ + if( this != ©_tensor){ + vec.clear(); + tensor_shape.clear(); + std::copy(copy_tensor.vec.begin(), copy_tensor.vec.end(),std::back_inserter(vec)); + std::copy(copy_tensor.tensor_shape.begin(),copy_tensor.tensor_shape.end(),std::back_inserter(tensor_shape)); + rank = copy_tensor.rank; + } + return *this; + } + + //Move Constructor + Tensor (Tensor<T>&& move_tensor) noexcept{ + vec = std::exchange(move_tensor.vec,{0}); + tensor_shape = std::exchange(move_tensor.tensor_shape,{0}); + rank = move_tensor.rank; + move_tensor.rank = 1; + } + + //Move Assignment Operator + Tensor& operator=(Tensor<T>&& move_tensor) noexcept{ + if(this == &move_tensor) return *this; + vec = std::exchange(move_tensor.vec,{0}); + tensor_shape = std::exchange(move_tensor.tensor_shape,{0}); + rank = move_tensor.rank; + move_tensor.rank = 1; + return *this; + } + + //Destructor + ~Tensor(){ + vec.clear(); + tensor_shape.clear(); + } + + int getRank()const{ + return rank; + } + + void setRank(const int& rank){ + this->rank = rank; + } + + std::vector<size_t> getShape()const{ + return tensor_shape; + } + + void setShape(const std::vector<size_t>& shape){ + tensor_shape = shape; + } + + std::vector<T> getVec()const{ + return vec; + } + + void setVec(const std::vector<T>& value ){ + vec.clear(); + std::copy(value.begin(),value.end(),std::back_inserter(vec)); + } + int numElements(){ + return numberElementsInShape(0); + } + + void printTensor(){ + for(int i=0;i<vec.size();i++){ + std::cout<<vec[i]<<' '; + } + std::cout<<std::endl; + std::cout<<"Size of the tensor is :"<<vec.size()<<std::endl; + } + + //overloaded operator to read the elements + const T& operator()(const std::vector<size_t>& idx )const{ + size_t index = 0; + for(int i=0 ; i<idx.size(); i++){ + index+= idx[i]*numberElementsInShape(i+1); + } + return vec[index]; + } + + //overloaded operator to write + T& operator()(const std::vector<size_t>& idx ){ + size_t index = 0; + for(int i=0 ; i<idx.size(); i++){ + index+= idx[i]*numberElementsInShape(i+1); + } + return vec[index]; + } + + /*T elementInTensor(const std::vector< size_t >& idx){ + int index = 0; + for(int i=0 ; i<idx.size(); i++){ + index+= idx[i]*numberElementsInShape(i+1); + } + return(vec[index]); + } + + void alterElementInTensor(const std::vector<size_t>& idx, const T& value){ + int index = 0; + for(int i=0 ; i<idx.size(); i++){ + index+= idx[i]*numberElementsInShape(i+1); + } + vec[index] = value; + }*/ + + private: + std::vector<T> vec = {0}; + std::vector<size_t> tensor_shape = {0}; + int rank =1; + int numberElementsInShape(const std::vector<size_t>& shape){ + int mulAns = 1; + for(auto i : shape){ + mulAns*=i; + } + return mulAns; + } + + void setTensorShape(const std::vector< size_t >& shape){ + tensor_shape = shape; + rank = shape.size(); + } + + int numberElementsInShape(const int& ind){ + int mulAns = 1; + for(int i =ind;i<tensor_shape.size();i++){ + mulAns*=tensor_shape[i]; + } + return mulAns; + } +}; + +template<Arithmetic T> +Tensor<T> readTensorFromFile(const std::string& filename){ + std::ifstream file(filename); + + if(!file){ + std::cerr<<"Error opening file"<<std::endl; + } + + Tensor<T> tensor; + int rankTemp; + file>>rankTemp; + tensor.setRank(rankTemp); + + std::vector<size_t> shapeTemp; + size_t ele; + for(size_t i =0; i<rankTemp ;i++){ + file>>ele; + shapeTemp.push_back(ele); + } + tensor.setShape(shapeTemp); + std::vector<T> vecTemp; + for(size_t i =0; i<tensor.numElements();i++){ + T eleTemp; + file>>eleTemp; + vecTemp.push_back(eleTemp); + } + tensor.setVec(vecTemp); + return tensor; +} + +template<Arithmetic T> +void writeToTensorFromFile(const Tensor<T>& tensor,const std::string& filename){ + std::ofstream file(filename); + if (!file) { + std::cerr << "Error opening file for writing: " << filename << std::endl; + return; + } + + int rank = tensor.getRank(); + file<<rank<<std::endl; + std::vector<size_t> shape = tensor.getShape(); + for(auto i : shape){ + file<<i<<std::endl; + } + std::vector<T> vec = tensor.getVec(); + for(auto i : vec){ + file<<i<<std::endl; + } +} + +int main(){ + // Create a 2x2x2 tensor + /*Tensor<int> tensor({2,2,2}); + // Fill tensor with values 0-7 in row-major order + tensor.alterElementInTensor({0,0,0},0); + tensor.alterElementInTensor({0,0,1},1); + tensor.alterElementInTensor({0,1,0},2); + tensor.alterElementInTensor({0,1,1},3); + tensor.alterElementInTensor({1,0,0},4); + tensor.alterElementInTensor({1,0,1},5); + tensor.alterElementInTensor({1,1,0},6); + tensor.alterElementInTensor({1,1,1},7); + // Get value at position [1,1,1] (should be 7) + int ans = tensor.elementInTensor({1,1,1}); + // Print full tensor and the retrieved value + tensor.printTensor(); + std::cout<<ans<<std::endl;*/ + + Tensor<double> tensor({2,2,2}); + /*tensor.alterElementInTensor({0,0,0},1.5); + tensor.alterElementInTensor({0,0,1},.6); + tensor.alterElementInTensor({0,1,0},8.7); + tensor.alterElementInTensor({0,1,1},3.5); + tensor.alterElementInTensor({1,0,0},1.4); + tensor.alterElementInTensor({1,0,1},5.3); + tensor.alterElementInTensor({1,1,0},6.2); + tensor.alterElementInTensor({1,1,1},7.1);*/ + + tensor({0,0,0}) =1.5; + tensor({0,0,1}) =.6; + tensor({0,1,0}) =8.7; + tensor({0,1,1}) =3.5; + tensor({1,0,0}) =1.4; + tensor({1,0,1}) =5.3; + tensor({1,1,0}) =6.2; + tensor({1,1,1}) =7.1; + + /*Tensor<double> tensor1({2,2,2}); + Tensor<double> tensor3; + tensor3 = std::move(tensor); + tensor.printTensor(); + tensor3.printTensor();*/ + /*std::cout<<tensor.getRank()<<std::endl; + std::cout<<tensor.getShape()[0]<<std::endl; + std::cout<<tensor.numElements()<<std::endl; + std::cout<<tensor({1,0,1})<<std::endl; + tensor.printTensor();*/ + /*Tensor<int> tensorFile = readTensorFromFile<int>("data/tensor_02"); + tensorFile.printTensor();*/ + // writeToTensorFromFile(tensor,"data/tensor_03"); + tensor.printTensor(); + return 0; +}