openGPMP
Open Source Mathematics Package
tensor.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  *
3  * Project
4  * _____ _____ __ __ _____
5  * / ____| __ \| \/ | __ \
6  * ___ _ __ ___ _ __ | | __| |__) | \ / | |__) |
7  * / _ \| '_ \ / _ \ '_ \| | |_ | ___/| |\/| | ___/
8  *| (_) | |_) | __/ | | | |__| | | | | | | |
9  * \___/| .__/ \___|_| |_|\_____|_| |_| |_|_|
10  * | |
11  * |_|
12  *
13  * Copyright (C) Akiel Aries, <akiel@akiel.org>, et al.
14  *
15  * This software is licensed as described in the file LICENSE, which
16  * you should have received as part of this distribution. The terms
17  * among other details are referenced in the official documentation
18  * seen here : https://akielaries.github.io/openGPMP/ along with
19  * important files seen in this project.
20  *
21  * You may opt to use, copy, modify, merge, publish, distribute
22  * and/or sell copies of the Software, and permit persons to whom
23  * the Software is furnished to do so, under the terms of the
24  * LICENSE file. As this is an Open Source effort, all implementations
25  * must be of the same methodology.
26  *
27  *
28  *
29  * This software is distributed on an AS IS basis, WITHOUT
30  * WARRANTY OF ANY KIND, either express or implied.
31  *
32  ************************************************************************/
34 #include <stdexcept>
35 
36 // Constructors
37 
38 gpmp::linalg::Tensor::Tensor() : data_({{{}}}), dimensions_{0, 0, 0} {
39 }
40 
41 gpmp::linalg::Tensor::Tensor(const std::vector<size_t> &dimensions) {
42  if (dimensions.empty()) {
43  throw std::invalid_argument("Error: Tensor dimensions are empty.");
44  }
45 
46  // Assign values to dimensions_
47  for (size_t i = 0; i < 3; ++i) {
48  dimensions_[i] = dimensions[i];
49  }
50 
51  size_t totalSize = 1;
52  for (size_t dim : dimensions) {
53  totalSize *= dim;
54  }
55  data_ = std::vector<std::vector<std::vector<double>>>(
56  dimensions_[0],
57  std::vector<std::vector<double>>(
58  dimensions_[1],
59  std::vector<double>(dimensions_[2], 0.0)));
60 }
61 
63  const std::vector<std::vector<std::vector<double>>> &data)
64  : data_(data) {
65  if (data.empty() || data[0].empty()) {
66  throw std::invalid_argument("Error: Tensor data is empty.");
67  }
68 
69  dimensions_[0] = data.size();
70  dimensions_[1] = data[0].size();
71  dimensions_[2] = data[0][0].size();
72 }
73 
76  if (dimensions_[0] != other.dimensions_[0] ||
77  dimensions_[1] != other.dimensions_[1] ||
78  dimensions_[2] != other.dimensions_[2]) {
79  throw std::invalid_argument(
80  "Error: Tensor dimensions do not match for addition.");
81  }
82 
83  gpmp::linalg::Tensor result;
84  result.data_ = data_;
85 
86  for (size_t i = 0; i < dimensions_[0]; ++i) {
87  for (size_t j = 0; j < dimensions_[1]; ++j) {
88  for (size_t k = 0; k < dimensions_[2]; ++k) {
89  result.data_[i][j][k] += other.data_[i][j][k];
90  }
91  }
92  }
93 
94  return result;
95 }
96 
98  gpmp::linalg::Tensor result;
99  result.data_ = data_;
100 
101  for (size_t i = 0; i < dimensions_[0]; ++i) {
102  for (size_t j = 0; j < dimensions_[1]; ++j) {
103  for (size_t k = 0; k < dimensions_[2]; ++k) {
104  result.data_[i][j][k] *= scalar;
105  }
106  }
107  }
108 
109  return result;
110 }
111 
113  if (dimensions_[2] != other.dimensions_[1]) {
114  throw std::invalid_argument(
115  "Error: Tensor dimensions do not match for multiplication.");
116  }
117 
118  gpmp::linalg::Tensor result;
119  result.dimensions_[0] = dimensions_[0];
120  result.dimensions_[1] = dimensions_[1];
121  result.dimensions_[2] = other.dimensions_[2];
122 
123  result.data_ = std::vector<std::vector<std::vector<double>>>(
124  dimensions_[0],
125  std::vector<std::vector<double>>(
126  dimensions_[1],
127  std::vector<double>(other.dimensions_[2], 0.0)));
128 
129  for (size_t i = 0; i < dimensions_[0]; ++i) {
130  for (size_t j = 0; j < dimensions_[1]; ++j) {
131  for (size_t k = 0; k < other.dimensions_[2]; ++k) {
132  for (size_t l = 0; l < dimensions_[2]; ++l) {
133  result.data_[i][j][k] +=
134  data_[i][j][l] * other.data_[l][j][k];
135  }
136  }
137  }
138  }
139 
140  return result;
141 }
142 
143 double gpmp::linalg::Tensor::get(const std::vector<size_t> &indices) const {
144  if (indices.size() != 3) {
145  throw std::out_of_range(
146  "Error: Invalid number of indices for tensor access.");
147  }
148 
149  for (size_t i = 0; i < 3; ++i) {
150  if (indices[i] >= dimensions_[i]) {
151  throw std::out_of_range(
152  "Error: Index out of bounds for tensor access.");
153  }
154  }
155 
156  return data_[indices[0]][indices[1]][indices[2]];
157 }
158 
159 void gpmp::linalg::Tensor::set(const std::vector<size_t> &indices,
160  double value) {
161  if (indices.size() != 3) {
162  throw std::out_of_range(
163  "Error: Invalid number of indices for tensor access.");
164  }
165 
166  for (size_t i = 0; i < 3; ++i) {
167  if (indices[i] >= dimensions_[i]) {
168  throw std::out_of_range(
169  "Error: Index out of bounds for tensor access.");
170  }
171  }
172 
173  data_[indices[0]][indices[1]][indices[2]] = value;
174 }
175 
177  for (size_t i = 0; i < dimensions_[0]; ++i) {
178  for (size_t j = 0; j < dimensions_[1]; ++j) {
179  for (size_t k = 0; k < dimensions_[2]; ++k) {
180  std::cout << data_[i][j][k] << " ";
181  }
182  std::cout << "\n";
183  }
184  std::cout << "\n";
185  }
186 }
Represents a 3D tensor with basic operations.
Definition: tensor.hpp:51
void set(const std::vector< size_t > &indices, double value)
Sets the value at the specified indices.
Definition: tensor.cpp:159
size_t dimensions_[3]
Definition: tensor.hpp:127
Tensor add(const Tensor &other) const
Adds another tensor to the current tensor.
Definition: tensor.cpp:75
double get(const std::vector< size_t > &indices) const
Gets the value at the specified indices.
Definition: tensor.cpp:143
void display() const
Displays the tensor.
Definition: tensor.cpp:176
Tensor multiply(double scalar) const
Multiplies the tensor by a scalar value.
Definition: tensor.cpp:97
Tensor()
Default constructor Creates an empty tensor.
Definition: tensor.cpp:38
std::vector< std::vector< std::vector< double > > > data_
< 3D vector representing the tensor data
Definition: tensor.hpp:125