Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
ROperator_Slice.hxx
Go to the documentation of this file.
1#ifndef TMVA_SOFIE_ROPERATOR_SLICE
2#define TMVA_SOFIE_ROPERATOR_SLICE
3
5#include "TMVA/ROperator.hxx"
6#include "TMVA/RModel.hxx"
7
8#include <cassert>
9#include <sstream>
10#include <numeric>
11
12namespace TMVA{
13namespace Experimental{
14namespace SOFIE{
15
16// slice operator
17
18template <typename IType>
20{
21
22private:
23
24 // flags to indicate if start/end and steps are not defined at compiled time
25 bool fIsStartUndef = false;
26 bool fIsEndUndef = false;
27 bool fIsStepUndef = false;
28 bool fIdentitySlice = false;
29 std::string fNData; // input data tensor name
30 std::string fNOutput; // output data name
31 std::vector<std::string> fNames; // tensor names for meta(axis) information
32 std::vector<Dim> fShapeInput; // input shape
33 std::vector<Dim> fShapeOutput; // output shape
34 std::vector<Dim> fOutputShapeData; // output shape data in case output is a shape param tensor
35
36 // saved Start/End.Steps are corrected from initial ONNX for negative/default values
37 // and are available for each axis
38 std::vector<Dim> fStart; // starting values of slices for all axes
39 std::vector<Dim> fEnd; // End values of slices for all axes
40 std::vector<Dim> fSteps; // step values of slices for all axes
41 std::vector<Dim> fStartDims; // input starting values of slices
42 std::vector<Dim> fEndDims; // input End values of slices
43 std::vector<Dim> fStepDims; // input step values of slices
44 std::vector<IType> fAxes; // axes for input start/emd/step values
45
46 std::vector<std::vector<IType>> fAttributes; // attributes for the version <=10 case
47
48
49public:
50
52
53 // ctor for versions >= 10
54 ROperator_Slice(std::string nameData, std::vector<std::string> names, std::string nameOutput)
55 : fNData(UTILITY::Clean_name(nameData)),
56 fNOutput(UTILITY::Clean_name(nameOutput))
57 {
58 fNames.resize(4);
59 // axes and steps can be optional
60 for (size_t i = 0; i < names.size(); ++i) {
61 fNames[i] = UTILITY::Clean_name(names[i]);
62 }
63
66 }
67 // ctor for versions < 10
68 ROperator_Slice(std::string nameData, std::vector<IType> starts, std::vector<IType> ends, std::vector<IType> axes, std::string nameOutput)
69 : fNData(UTILITY::Clean_name(nameData)),
70 fNOutput(UTILITY::Clean_name(nameOutput))
71 {
72 fAttributes.push_back(starts);
73 fAttributes.push_back(ends);
74 fAttributes.push_back(axes);
75 }
76
77
78
79 void Initialize(RModel& model) override {
80 if (model.CheckIfTensorAlreadyExist(fNData) == false){ //input must be a graph input, or already initialized intermediate tensor
81 throw std::runtime_error("TMVA Slice Op Input Tensor is not found in model");
82 }
83
84 std::vector<std::vector<Dim>> shapes;
86 shapes.push_back(fShapeInput);
87
88 std::vector<std::vector<IType>> itensors(4);
89
90 if (fNames.size() > 0) { // size has to be equal to 4
91 // loop on the extra 2 or 3 or 4 inputs
92 for (size_t i = 0; i < 4; ++i) {
93 if (!fNames[i].empty()) {
94 if (model.IsInitializedTensor(fNames[i])) {
95 auto dptr = model.GetInitializedTensorData(fNames[i]);
96 auto tensor = static_cast<IType *>(dptr.get());
97 auto vec = model.GetTensorShape(fNames[i]);
98 assert(vec.size() == 1);
99 itensors[i] = std::vector<IType>(tensor, tensor + vec[0]);
100
101 } else if (model.IsShapeTensor(fNames[i])) {
102 // case is a shape tensor
103 if (i == 0) {
105 } else if (i == 1) {
107 } else if (i == 3) {
109 }
110 } else {
111 // case is an intermediate tensor
112 auto shape = model.GetTensorShape(fNames[i]);
113 size_t s = shape[0];
114 for (size_t k = 0; k < s; k++) {
115 if (i == 0) {
116 fStartDims.push_back( Dim{std::string("start_") + fNOutput + "_" + std::to_string(k)});
117 fIsStartUndef = true;
118 } else if (i == 1) {
119 fEndDims.push_back(Dim{std::string("end_") + fNOutput + "_" + std::to_string(k)});
120 fIsEndUndef = true;
121 } else if (i == 3) {
122 fStepDims.push_back(Dim{std::string("step_") + fNOutput + "_" + std::to_string(k)});
123 fIsStepUndef = true;
124 }
125 }
126 }
127 }
128 }
129 } else {
130 // old slice versions
131 assert(fAttributes.size() > 1);
132 for (size_t i = 0; i < fAttributes.size(); i++) {
133 itensors[i] = fAttributes[i];
134 }
135 }
136 size_t dim = fShapeInput.size();
137
138 // default values
139 fSteps = std::vector<Dim>(dim, Dim{1});
140 fStart = std::vector<Dim>(dim, Dim{0});
142
143 // default axes
144 if (itensors[2].empty()) {
145 fAxes.resize(dim);
146 std::iota(fAxes.begin(), fAxes.end(), 0);
147 } else {
148 fAxes = itensors[2];
149 for (size_t i = 0; i < fAxes.size(); i++) {
150 // negative axes - they count from the back
151 if (fAxes[i] < 0) fAxes[i] = dim + fAxes[i];
152 if (fAxes[i] < 0 || fAxes[i] >= static_cast<IType>(dim))
153 throw std::runtime_error("TMVA Slice Op : invalid axis value " + std::to_string(fAxes[i]) +
154 " for " + std::to_string(i));
155 }
156 }
157 // Loop on axis to get start/end/step values
158 for (size_t i = 0; i < fAxes.size(); i++) {
159 if (!itensors[0].empty() )
160 fStartDims.push_back(Dim{ static_cast<size_t>(itensors[0][i])});
161 if (fStartDims.empty())
162 throw std::runtime_error("TMVA Slice Op : Missing start input tensor");
163
164 if (!itensors[1].empty())
165 fEndDims.push_back(Dim{ static_cast<size_t>(itensors[1][i])});
166 else if (fEndDims.empty())
167 throw std::runtime_error("TMVA Slice Op : Missing end input tensor");
168
169 if (!itensors[3].empty()) {
170 fStepDims.push_back(Dim{ static_cast<size_t>(itensors[3][i])});
171 }
172 else if (fStepDims.size() < fAxes.size()) // this can happen since it is optional
173 fStepDims.push_back(Dim{size_t(1)});
174
175 if (!fShapeInput[fAxes[i]].isParam) {
176 size_t iAxisDim = fShapeInput[fAxes[i]].dim;
177 //correct values if too large or too small
178 IType istart = 0;
179 if (!fStartDims[i].isParam) {
180 istart = static_cast<IType>(fStartDims[i].dim);
181 if (istart < 0) istart = iAxisDim + istart;
182 }
183 IType iend = static_cast<IType>(iAxisDim);
184 if (!fEndDims[i].isParam) {
185 iend = static_cast<IType>(fEndDims[i].dim);
186 if (iend < 0) iend = iAxisDim + iend;
187 }
188 //steps
189 IType istep = 1;
190 if (!fStepDims[i].isParam) {
191 istep = static_cast<IType>(fStepDims[i].dim);
192 } else {
193 throw std::runtime_error("TMVA Slice Op : parametric step inputs are not supported");
194 }
195 // clamp start end values depending on steps
196 // start must be [0,N] for positive steps or [0,N-1] for negative
197 // end must be [0,N] for positive steps or [-1, N-1] for negative
198 if (istart < 0) istart = 0;
199 if (istep > 0) {
200 if (istart > static_cast<IType>(iAxisDim)) istart = static_cast<IType>(iAxisDim);
201 if (iend < 0) iend = 0;
202 if (iend > static_cast<IType>(iAxisDim)) iend = static_cast<IType>(iAxisDim);
203 } else if (istep < 0) {
204 if (istart > static_cast<IType>(iAxisDim)-1) istart = static_cast<IType>(iAxisDim) -1;
205 if (iend < -1) iend = -1;
206 if (iend > static_cast<IType>(iAxisDim)-1) iend = static_cast<IType>(iAxisDim) -1;
207 } else {
208 throw std::runtime_error("TMVA Slice Op : invalid step value " + std::to_string(istep) +
209 " for " + std::to_string(i));
210 }
211 // for parametric values clamping we will done at run time
212 if (fStartDims[i].isParam)
213 fStart[fAxes[i]] = fStartDims[i];
214 else
215 fStart[fAxes[i]] = Dim{size_t(istart)};
216 if (fStartDims[i].isParam)
217 fEnd[fAxes[i]] = fEndDims[i];
218 else
219 fEnd[fAxes[i]] = Dim{size_t(iend)};
220
221 fSteps[fAxes[i]] = Dim{size_t(istep)};
222 } else {
223 //std::cout << i << " Param dim for " << fAxes[i] << " " << fShapeInput[fAxes[i]] << std::endl;
224 // correct only negative values
225 if (!fStartDims[i].isParam) {
226 IType istart = static_cast<IType>(fStartDims[i].dim);
227 if (istart < 0) {
228 std::string sstart = std::string("(") + fShapeInput[fAxes[i]].param + "-" + std::to_string(-istart) +")";
229 fStart[fAxes[i]] = Dim{sstart,size_t(-1)};
230 } else {
231 fStart[fAxes[i]] = Dim{size_t(istart)};
232 }
233 } else {
234 fStart[fAxes[i]] = fStartDims[i];
235 }
236 if (!fEndDims[i].isParam) {
237 IType iend = static_cast<IType>(fEndDims[i].dim);
238 if (iend < 0) {
239 std::string send = std::string("(") + fShapeInput[fAxes[i]].param + "-" + std::to_string(-iend) +")";
240 fEnd[fAxes[i]] = Dim{send,size_t(-1)};
241 } else if (iend == std::numeric_limits<IType>::max()){
242 fEnd[fAxes[i]] = fShapeInput[fAxes[i]];
243 } else {
244 fEnd[fAxes[i]] = Dim{size_t(iend)};
245 }
246 } else {
247 fEnd[fAxes[i]] = fEndDims[i];
248 }
249
250 fSteps[fAxes[i]] = fStepDims[i];
251 }
252
253 }
254 // find output shape
255 fShapeOutput.resize(dim);
256 for (size_t i = 0; i < dim; i++) {
257 if (!fEnd[i].isParam && !fStart[i].isParam && !fSteps[i].isParam) {
258 int64_t istart = static_cast<int64_t>(fStart[i].dim);
259 int64_t iend = static_cast<int64_t>(fEnd[i].dim);
260 int64_t istep= static_cast<int64_t>(fSteps[i].dim);
261 int64_t s = (iend-istart)/istep;
262 fShapeOutput[i] = Dim{static_cast<size_t>(s)};
263 } else {
264 std::string s;
265 if (fStart[i].GetVal() != "0")
266 s = "(" + fEnd[i].GetVal() + "-" + fStart[i].GetVal() + ")";
267 else
268 s = fEnd[i].GetVal();
269 if (fSteps[i].GetVal() != "1") {
270 s.insert(0,"(");
271 s += ")/" + fSteps[i].GetVal() + ")";
272 }
273 fShapeOutput[i] = Dim{s,size_t(-1)};
274 // add also the shape parameters to RModel to declare them when
275 // allocating output tensor
276 if (fEnd[i].isParam && fEnd[i].dim != size_t(-1))
277 model.AddShapeParam(fEnd[i].param,fEnd[i].dim );
278 if (fStart[i].isParam && fStart[i].dim != size_t(-1))
279 model.AddShapeParam(fStart[i].param,fStart[i].dim );
280 if (fSteps[i].isParam && fSteps[i].dim != size_t(-1))
281 model.AddShapeParam(fSteps[i].param,fSteps[i].dim );
282
283 }
284 }
285 // case input is a constant tensor and of int64 type
286 if (model.IsInitializedTensor(fNData) && model.GetTensorType(fNData) == ETensorType::INT64) {
287 fIsOutputConstant = true;
288 auto inputData = static_cast<int64_t*>(model.GetInitializedTensorData(fNData).get());
289 size_t outputSize = ConvertShapeToLength(ConvertShapeToInt(fShapeOutput));
290 std::vector<int64_t> outputData(outputSize);
291 std::vector<size_t> inputStride = UTILITY::ComputeStrideFromShape(ConvertShapeToInt(fShapeInput));
292 if (model.Verbose()) {
293 std::cout << "Do slice for initialized input ..(start, end, step)\n";
294 for (size_t ii = 0; ii< fStart.size(); ii++)
295 std::cout << fStart [ii] << " " << fEnd[ii] << " " << fSteps[ii] << std::endl;
296 }
297 // perform slice using a recursive function- need to use two lambda functions for this
298 auto sliceRecursive = [&](size_t iaxis, size_t & outIdx, size_t & inOffset) {
299 auto slice_impl = [&](size_t iax, size_t & outputIdx, size_t & inputOffset, auto & sliceRecImpl) {
300 if (fStart[iax].isParam || fEnd[iax].isParam || fSteps[iax].isParam)
301 throw std::runtime_error("TMVA Slice Op : cannot have parametric values when input is constant");
302 // compute indices
303 std::vector<IType> indices;
304 for (IType i = (IType) fStart[iax].dim; (IType(fSteps[iax].dim) > 0) ? i < IType(fEnd[iax].dim) : i > IType(fEnd[iax].dim); i += IType(fSteps[iax].dim) )
305 indices.push_back(i);
306 if (iax == dim-1) { // last axis
307 for (size_t i = 0; i < indices.size(); i++) {
308 outputData[outputIdx] = inputData[inputOffset + indices[i]];
309 outputIdx++;
310 }
311 return;
312 } else {
313 for (size_t i = 0; i < indices.size(); i++) {
314 size_t offset = inputOffset + inputStride[iax]*indices[i];
316 }
317 }
318 };
320 };
321 size_t idx = 0;
322 size_t offset = 0;
323 sliceRecursive(0, idx, offset);
324
325 model.AddConstantTensor<int64_t>(fNOutput, ConvertShapeToInt(fShapeOutput), outputData.data());
326 if (model.Verbose()) {
327 std::cout << "Slice: output is a constant tensor " << ConvertDimShapeToString(fShapeOutput) << " : "
328 << ConvertValuesToString(outputData) << std::endl;
329 }
330 }
331 else if (model.IsShapeTensor(fNData) && !fStart[0].isParam && !fEnd[0].isParam) {
332 // case of input is a shape tensor. In this case rank=1 always, axis =0 and Slice is trivial
333 auto inputData = model.GetShapeTensorValues(fNData);
334 fOutputShapeData = std::vector<Dim>(inputData.begin() + fStart[0].dim, inputData.begin() + fEnd[0].dim);
335 // try to convert to integer values if possible
336 auto outputData = ConvertShapeToInt(fOutputShapeData);
337 fShapeOutput = { Dim{fOutputShapeData.size()}};
338 if (outputData.empty()) {
339 // is a param shape tensor
340 model.AddShapeTensor(fNOutput, fOutputShapeData);
341 fIsOutputParamShape = true;
342 if (model.Verbose()) {
343 std::cout << "Slice: output is a shape tensor -> " << fNOutput << " " << ConvertDimShapeToString(fShapeOutput) << " with values "
344 << ConvertDimShapeToString(fOutputShapeData) << " (shape)" << std::endl;
345 }
346 } else {
347 fIsOutputConstant = true;
348 std::vector<int64_t> data(outputData.size());
349 std::copy(outputData.begin(), outputData.end(), data.begin());
350 model.AddConstantTensor<int64_t>(fNOutput, {data.size()}, data.data());
351 if (model.Verbose()) {
352 std::cout << "Slice: output is a constant tensor -> " << fNOutput << " " << ConvertDimShapeToString(fShapeOutput) << " with values "
353 << ConvertDimShapeToString(fOutputShapeData) << " constant " << std::endl;
354 }
355 }
356 }
357 else {
358 // check if Slice is just an Identity operator in case start = 0, end = input_shape and step=1
359 size_t ndim = fShapeInput.size();
360 fIdentitySlice = fShapeOutput.size() == ndim;
361 // check also if input data is not input to the model. In that case we copy the data since we cannot just copy from the input pointer
362 fIdentitySlice &= (!model.IsReadyInputTensor(fNData) && !model.IsDimInputTensor(fNData));
363 for (size_t idim = 0; idim < ndim; idim++) {
364 if (!fIdentitySlice) break;
365 fIdentitySlice &= (fStart[idim].GetVal() == "0");
366 fIdentitySlice &= (fSteps[idim].GetVal() == "1");
367 fIdentitySlice &= (fEnd[idim].GetVal() == fShapeInput[idim].GetVal());
368 }
369
370 model.AddIntermediateTensor(fNOutput, model.GetTensorType(fNData), fShapeOutput);
371 //if (fIdentitySlice) model.AddAliasTensor(fNOutput, fNData);
372
373 if (model.Verbose()) {
374 std::cout << "Slice " << fNData << " " << ConvertDimShapeToString(fShapeInput)
375 << "---> " << fNOutput << " " << ConvertDimShapeToString(fShapeOutput);
376 if (fIdentitySlice) std::cout << " (using alias tensor since slice is an identity) ";
377 std::cout << std::endl;
378
379 }
380 }
381 }
382
383 std::string Generate(std::string opName) override {
384
385 if (fShapeInput.empty() || fShapeOutput.empty()){
386 throw std::runtime_error("TMVA SOFIE Slice Op called to Generate without being initialized first");
387 }
388
389 std::stringstream out;
390
391 out << "///------- Slice operator " << opName << "---> " << fNOutput << " "
392 << ConvertDimShapeToString(fShapeOutput) << "\n" << std::endl;
393 if (fIsOutputConstant) return out.str(); //no op for constant tensors
394 if (fIsOutputParamShape) {
395 out << "/// Slice output is a shape tensor with values : " << ConvertDimShapeToString(fShapeOutput) << "\n";
396 // need to generate code assigning values to shape tensors
397 for (int i = 0; i < static_cast<int>(fShapeOutput[0].dim); i++) {
398 out << SP << "tensor_" << fNOutput << "[" << i << "] = " << fOutputShapeData[i] << ";\n";
399 }
400 return out.str();
401 }
402
403 size_t ndim = fShapeInput.size();
404
405 if (fIdentitySlice) {
406 out << "/// Slice is just an identity (copy) \n";
407 //out << SP << "tensor_" << fNOutput << " = const_cast<" << ConvertTypeToString(fOutputType) << " *>(tensor_" << fNData << ");\n";
408 out << SP << "std::copy(tensor_" << fNData << ", tensor_" << fNData << " + " << ConvertDimShapeToLength(fShapeInput) << ", tensor_" << fNOutput << ");\n";
409 return out.str();
410 }
411
412 // loop on the dimensions depending no the orders
413 auto strides = UTILITY::ComputeStrideFromShape(fShapeInput);
414
415
416 out << SP << "{\n"; // define operator scope
417 for (size_t i = 0; i < fStepDims.size(); i++) {
418 if (fStepDims[i].isParam) {
419 if (fIsStepUndef)
420 out << SP << "size_t " << fStepDims[i] << " = tensor_" << fNames[3] << "[" << i << "];\n";
421 }
422 }
423 // special case for parametric values for start/end. Need to do clipping
424 for (size_t i = 0; i < fStartDims.size(); i++) {
425 if (fStartDims[i].isParam && fStartDims[i].param != fShapeInput[fAxes[i]].param) {
426 std::string s_start = "start_" + std::to_string(i);
427 if (fIsStartUndef) {
428 s_start = fStartDims[i].param;
429 out << SP << "size_t " << s_start << " = tensor_" << fNames[0] << "[" << i << "];\n";
430 } else {
431 out << SP << "size_t " << s_start << " = " << fStartDims[i] << ";\n";
432 fStart[fAxes[i]] = s_start; // need to use this value later when slicing
433 }
434 out << SP << "if (" << s_start << " < 0) " << s_start << " += " << fShapeInput[fAxes[i]] <<";\n";
435 out << SP << "if (" << s_start << " < 0) " << s_start << " = 0;\n";
436 if (!fStepDims[i].isParam) {
437 if (static_cast<IType>(fStepDims[i].dim) > 0 )
438 out << SP << "if (" << s_start << " > " << fShapeInput[fAxes[i]] << " ) " << s_start << " = " << fShapeInput[fAxes[i]] <<";\n";
439 else
440 out << SP << "if (" << s_start << " > " << fShapeInput[fAxes[i]] << " - 1" << " ) " << s_start << " = " << fShapeInput[fAxes[i]] << " - 1;\n";
441 }
442 }
443 // special case if step is negative and shape are equal and step is negative
444 else if (fStartDims[i].isParam && fStartDims[i].param == fShapeInput[fAxes[i]].param && !fStepDims[i].isParam && static_cast<IType>(fStepDims[i].dim) < 0 ) {
445 fStart[fAxes[i]] = Dim{ fStartDims[i].param + "-1" };
446 }
447 }
448 // now to for end
449 for (size_t i = 0; i < fEndDims.size(); i++) {
450 if (fEndDims[i].isParam && fEndDims[i].param != fShapeInput[fAxes[i]].param) {
451 std::string s_end = "end_" + std::to_string(i);
452 if (fIsEndUndef) {
453 s_end = fEndDims[i].param;
454 out << SP << "size_t " << s_end << " = tensor_" << fNames[1] << "[" << i << "];\n";
455 } else {
456 out << SP << "size_t " << s_end << " = " << fEndDims[i] << ";\n";
457 fEnd[fAxes[i]] = s_end; // need to use this value later when slicing
458 }
459 out << SP << "if (" << s_end << " < 0) " << s_end << " += " << fShapeInput[fAxes[i]] <<";\n";
460 if (!fStepDims[i].isParam) {
461 if (static_cast<IType>(fStepDims[i].dim) > 0 ) {
462 out << SP << "if (" << s_end << " < 0) " << s_end << " = 0;\n";
463 out << SP << "if (" << s_end << " > " << fShapeInput[fAxes[i]] << " ) " << s_end << " = " << fShapeInput[fAxes[i]] <<";\n";
464 } else {
465 out << SP << "if (" << s_end << " < -1) " << s_end << " = -1;\n";
466 out << SP << "if (" << s_end << " > " << fShapeInput[fAxes[i]] << " - 1" << " ) " << s_end << " = " << fShapeInput[fAxes[i]] << " - 1;\n";
467 }
468 }
469 }
470 // special case if step is negative and shape are equal and step is negative
471 else if (fEndDims[i].isParam && fEndDims[i].param == fShapeInput[fAxes[i]].param && !fStepDims[i].isParam && static_cast<IType>(fStepDims[i].dim) < 0 ) {
472 fEnd[fAxes[i]] = Dim{ fEndDims[i].param + "-1" };
473 }
474 }
475
476 out << SP << "size_t iOut = 0;\n";
477 std::string MSP = SP;
478 for (size_t idim = 0; idim < ndim; idim++) {
479 out << MSP << "for (size_t i" << idim << " = " << fStart[idim] << "; i" << idim << " < " << fEnd[idim]
480 << "; i" << idim << "+= " << fSteps[idim] << ") {\n";
481 MSP += SP;
482 if (idim < ndim-1) out << MSP << "size_t stride" << idim << " = " << strides[idim] << "*i" << idim << ";\n";
483 }
484 out << MSP << "size_t iInput = ";
485 for (size_t idim = 0; idim < ndim-1; idim++) out << " stride" << idim << " + ";
486 // here should be step size ?
487 out << "i" << ndim-1 << ";\n";
488 out << MSP << "tensor_" << fNOutput << "[iOut++] = tensor_" <<fNData << "[iInput];\n";
489 for (size_t idim = 0; idim < ndim; idim++) {
490 MSP = MSP.replace(0,SP.length(),"");
491 out << MSP << "}\n";
492 }
493 out << SP << "}\n"; // end operator scope
494
495 return out.str();
496 }
497
498};
499
500}//SOFIE
501}//Experimental
502}//TMVA
503
504
505#endif //TMVA_SOFIE_ROPERATOR_SLICE
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h offset
const_iterator begin() const
const_iterator end() const
std::vector< size_t > GetTensorShape(const std::string &name) const
Definition RModel.cxx:64
std::vector< Dim > GetDimTensorShape(const std::string &name) const
Definition RModel.cxx:100
bool CheckIfTensorAlreadyExist(std::string tensor_name)
Definition RModel.cxx:157
bool IsShapeTensor(const std::string &name) const
check if a tensor is a shape tensor
Definition RModel.cxx:260
bool IsInitializedTensor(const std::string &name) const
Definition RModel.cxx:273
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
Definition RModel.cxx:366
const std::vector< Dim > & GetShapeTensorValues(const std::string &tensor_name) const
Definition RModel.cxx:268
std::vector< std::vector< IType > > fAttributes
ROperator_Slice(std::string nameData, std::vector< IType > starts, std::vector< IType > ends, std::vector< IType > axes, std::string nameOutput)
ROperator_Slice(std::string nameData, std::vector< std::string > names, std::string nameOutput)
std::string Generate(std::string opName) override
std::vector< std::string_view > fInputTensorNames
Definition ROperator.hxx:50
std::vector< std::string_view > fOutputTensorNames
Definition ROperator.hxx:51
std::string Clean_name(std::string input_tensor_name)
std::vector< size_t > ComputeStrideFromShape(const std::vector< size_t > &shape)
compute stride of a tensor given its shape (assume layout is row-major)
std::string ConvertDimShapeToString(const std::vector< Dim > &shape)
std::size_t ConvertShapeToLength(const std::vector< size_t > &shape)
std::string ConvertValuesToString(size_t n, const T *data, size_t maxprint=-1)
std::vector< size_t > ConvertShapeToInt(const std::vector< Dim > &shape)
Convert shape based on Dim to integer format.
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
create variable transformations