v2.0.0
Loading...
Searching...
No Matches
ml_tensor.cpp
Go to the documentation of this file.
1//=============================================================================================================
28
29//=============================================================================================================
30// INCLUDES
31//=============================================================================================================
32
33#include "ml_tensor.h"
34
35//=============================================================================================================
36// STL INCLUDES
37//=============================================================================================================
38
39#include <algorithm>
40#include <cstring>
41#include <numeric>
42#include <stdexcept>
43
44//=============================================================================================================
45// USED NAMESPACES
46//=============================================================================================================
47
48using namespace MLLIB;
49using namespace Eigen;
50
51//=============================================================================================================
52// STATIC HELPERS
53//=============================================================================================================
54
55int64_t MlTensor::computeSize(const std::vector<int64_t>& shape)
56{
57 // An empty shape is a scalar with one element, as in ONNX and NumPy
58 return std::accumulate(shape.begin(), shape.end(),
59 int64_t(1), std::multiplies<int64_t>());
60}
61
62//=============================================================================================================
63// DEFINE MEMBER METHODS
64//=============================================================================================================
65
67: m_storage(nullptr)
68, m_data(nullptr)
69, m_shape()
70, m_size(0)
71{
72}
73
74//=============================================================================================================
75
76MlTensor::MlTensor(std::vector<float>&& data, std::vector<int64_t> shape)
77: m_shape(std::move(shape))
78, m_size(computeSize(m_shape))
79{
80 if (static_cast<int64_t>(data.size()) != m_size) {
81 throw std::invalid_argument("MlTensor: buffer size does not match shape");
82 }
83 m_storage = std::make_shared<std::vector<float>>(std::move(data));
84 m_data = m_storage->data();
85}
86
87//=============================================================================================================
88
89MlTensor::MlTensor(const float* data, std::vector<int64_t> shape)
90: m_shape(std::move(shape))
91, m_size(computeSize(m_shape))
92{
93 m_storage = std::make_shared<std::vector<float>>(data, data + m_size);
94 m_data = m_storage->data();
95}
96
97//=============================================================================================================
98
99MlTensor::MlTensor(const MatrixXf& mat)
100: m_shape({mat.rows(), mat.cols()})
101, m_size(mat.size())
102{
103 m_storage = std::make_shared<std::vector<float>>(static_cast<size_t>(m_size));
104 m_data = m_storage->data();
105 // Copy column-major Eigen → row-major contiguous storage (one memop)
106 Map<RowMajorMatrixXf>(m_data, mat.rows(), mat.cols()) = mat;
107}
108
109//=============================================================================================================
110
111MlTensor::MlTensor(const MatrixXd& mat)
112: m_shape({mat.rows(), mat.cols()})
113, m_size(mat.size())
114{
115 m_storage = std::make_shared<std::vector<float>>(static_cast<size_t>(m_size));
116 m_data = m_storage->data();
117 Map<RowMajorMatrixXf>(m_data, mat.rows(), mat.cols()) = mat.cast<float>();
118}
119
120//=============================================================================================================
121
122MlTensor MlTensor::view(float* data, std::vector<int64_t> shape)
123{
124 MlTensor t;
125 t.m_shape = std::move(shape);
126 t.m_size = computeSize(t.m_shape);
127 t.m_storage = nullptr; // non-owning
128 t.m_data = data;
129 return t;
130}
131
132//=============================================================================================================
133
135{
136 return MlTensor(data, {static_cast<int64_t>(rows), static_cast<int64_t>(cols)});
137}
138
139//=============================================================================================================
140
141int MlTensor::ndim() const
142{
143 return static_cast<int>(m_shape.size());
144}
145
146//=============================================================================================================
147
148int64_t MlTensor::size() const
149{
150 return m_size;
151}
152
153//=============================================================================================================
154
155const std::vector<int64_t>& MlTensor::shape() const
156{
157 return m_shape;
158}
159
160//=============================================================================================================
161
162int64_t MlTensor::shape(int dim) const
163{
164 if (dim < 0)
165 dim += ndim();
166 assert(dim >= 0 && dim < ndim());
167 return m_shape[static_cast<size_t>(dim)];
168}
169
170//=============================================================================================================
171
172int MlTensor::rows() const
173{
174 assert(ndim() >= 1);
175 return static_cast<int>(m_shape[0]);
176}
177
178//=============================================================================================================
179
180int MlTensor::cols() const
181{
182 assert(ndim() >= 2);
183 return static_cast<int>(m_shape[1]);
184}
185
186//=============================================================================================================
187
189{
190 return m_data;
191}
192
193//=============================================================================================================
194
195const float* MlTensor::data() const
196{
197 return m_data;
198}
199
200//=============================================================================================================
201
203{
204 assert(ndim() == 2);
205 return RowMajorMatrixMap(m_data, m_shape[0], m_shape[1]);
206}
207
208//=============================================================================================================
209
211{
212 assert(ndim() == 2);
213 return ConstRowMajorMatrixMap(m_data, m_shape[0], m_shape[1]);
214}
215
216//=============================================================================================================
217
218MatrixXf MlTensor::toMatrixXf() const
219{
220 assert(ndim() == 2);
221 // Assign row-major map to column-major MatrixXf (Eigen transposes layout)
222 return Map<const RowMajorMatrixXf>(m_data, m_shape[0], m_shape[1]);
223}
224
225//=============================================================================================================
226
227MatrixXd MlTensor::toMatrixXd() const
228{
229 assert(ndim() == 2);
230 return Map<const RowMajorMatrixXf>(m_data, m_shape[0], m_shape[1]).cast<double>();
231}
232
233//=============================================================================================================
234
235MlTensor MlTensor::reshape(std::vector<int64_t> newShape) const
236{
237 int64_t newSize = computeSize(newShape);
238 if (newSize != m_size) {
239 throw std::invalid_argument("MlTensor::reshape: new shape size differs from current");
240 }
241
242 MlTensor t;
243 t.m_storage = m_storage; // share ownership (or null for views)
244 t.m_data = m_data;
245 t.m_shape = std::move(newShape);
246 t.m_size = newSize;
247 return t;
248}
249
250//=============================================================================================================
251
253{
254 return m_storage == nullptr && m_data != nullptr;
255}
256
257//=============================================================================================================
258
259bool MlTensor::empty() const
260{
261 return m_size == 0;
262}
N-dimensional, row-major, reference-counted float32 tensor used as the universal MLLIB data carrier.
Tensors, model abstraction, ONNX Runtime inference and Python training drivers used across mne-cpp.
int cols() const
Eigen::MatrixXf toMatrixXf() const
Eigen::Map< RowMajorMatrixXf > RowMajorMatrixMap
Definition ml_tensor.h:80
static MlTensor fromBuffer(const float *data, int rows, int cols)
Eigen::MatrixXd toMatrixXd() const
static MlTensor view(float *data, std::vector< int64_t > shape)
int ndim() const
RowMajorMatrixMap matrix()
int64_t size() const
int rows() const
MlTensor reshape(std::vector< int64_t > newShape) const
bool empty() const
const std::vector< int64_t > & shape() const
bool isView() const
Eigen::Map< const RowMajorMatrixXf > ConstRowMajorMatrixMap
Definition ml_tensor.h:81