80 if (model.CheckIfTensorAlreadyExist(
fNData) ==
false){
81 throw std::runtime_error(
"TMVA Slice Op Input Tensor is not found in model");
84 std::vector<std::vector<Dim>> shapes;
88 std::vector<std::vector<IType>>
itensors(4);
92 for (
size_t i = 0; i < 4; ++i) {
94 if (model.IsInitializedTensor(
fNames[i])) {
95 auto dptr = model.GetInitializedTensorData(
fNames[i]);
97 auto vec = model.GetTensorShape(
fNames[i]);
101 }
else if (model.IsShapeTensor(
fNames[i])) {
112 auto shape = model.GetTensorShape(
fNames[i]);
114 for (
size_t k = 0; k < s; k++) {
149 for (
size_t i = 0; i <
fAxes.size(); i++) {
153 throw std::runtime_error(
"TMVA Slice Op : invalid axis value " + std::to_string(
fAxes[i]) +
154 " for " + std::to_string(i));
158 for (
size_t i = 0; i <
fAxes.size(); i++) {
162 throw std::runtime_error(
"TMVA Slice Op : Missing start input tensor");
167 throw std::runtime_error(
"TMVA Slice Op : Missing end input tensor");
193 throw std::runtime_error(
"TMVA Slice Op : parametric step inputs are not supported");
203 }
else if (
istep < 0) {
208 throw std::runtime_error(
"TMVA Slice Op : invalid step value " + std::to_string(
istep) +
209 " for " + std::to_string(i));
239 std::string send = std::string(
"(") +
fShapeInput[
fAxes[i]].param +
"-" + std::to_string(-
iend) +
")";
241 }
else if (
iend == std::numeric_limits<IType>::max()){
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);
262 fShapeOutput[i] = Dim{
static_cast<size_t>(s)};
265 if (fStart[i].GetVal() !=
"0")
266 s =
"(" + fEnd[i].GetVal() +
"-" + fStart[i].GetVal() +
")";
268 s = fEnd[i].GetVal();
269 if (fSteps[i].GetVal() !=
"1") {
271 s +=
")/" + fSteps[i].GetVal() +
")";
273 fShapeOutput[i] = Dim{s,size_t(-1)};
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 );
287 fIsOutputConstant =
true;
288 auto inputData =
static_cast<int64_t*
>(model.GetInitializedTensorData(fNData).get());
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;
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");
303 std::vector<IType> indices;
305 indices.push_back(i);
307 for (
size_t i = 0; i < indices.size(); i++) {
313 for (
size_t i = 0; i < indices.size(); i++) {
326 if (model.Verbose()) {
331 else if (model.IsShapeTensor(fNData) && !fStart[0].isParam && !fEnd[0].isParam) {
333 auto inputData = model.GetShapeTensorValues(fNData);
337 fShapeOutput = { Dim{fOutputShapeData.size()}};
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 "
347 fIsOutputConstant =
true;
351 if (model.Verbose()) {
352 std::cout <<
"Slice: output is a constant tensor -> " << fNOutput <<
" " <<
ConvertDimShapeToString(fShapeOutput) <<
" with values "
359 size_t ndim = fShapeInput.size();
360 fIdentitySlice = fShapeOutput.size() == ndim;
364 if (!fIdentitySlice)
break;
365 fIdentitySlice &= (fStart[
idim].GetVal() ==
"0");
366 fIdentitySlice &= (fSteps[
idim].GetVal() ==
"1");
367 fIdentitySlice &= (fEnd[
idim].GetVal() == fShapeInput[
idim].GetVal());
373 if (model.Verbose()) {
376 if (fIdentitySlice) std::cout <<
" (using alias tensor since slice is an identity) ";
377 std::cout << std::endl;
385 if (fShapeInput.empty() || fShapeOutput.empty()){
386 throw std::runtime_error(
"TMVA SOFIE Slice Op called to Generate without being initialized first");
389 std::stringstream out;
391 out <<
"///------- Slice operator " <<
opName <<
"---> " << fNOutput <<
" "
393 if (fIsOutputConstant)
return out.str();
394 if (fIsOutputParamShape) {
398 out <<
SP <<
"tensor_" << fNOutput <<
"[" << i <<
"] = " << fOutputShapeData[i] <<
";\n";
403 size_t ndim = fShapeInput.size();
405 if (fIdentitySlice) {
406 out <<
"/// Slice is just an identity (copy) \n";
408 out <<
SP <<
"std::copy(tensor_" << fNData <<
", tensor_" << fNData <<
" + " <<
ConvertDimShapeToLength(fShapeInput) <<
", tensor_" << fNOutput <<
");\n";
413 auto strides = UTILITY::ComputeStrideFromShape(fShapeInput);
417 for (
size_t i = 0; i < fStepDims.size(); i++) {
418 if (fStepDims[i].isParam) {
420 out <<
SP <<
"size_t " << fStepDims[i] <<
" = tensor_" << fNames[3] <<
"[" << i <<
"];\n";
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);
429 out <<
SP <<
"size_t " <<
s_start <<
" = tensor_" << fNames[0] <<
"[" << i <<
"];\n";
431 out <<
SP <<
"size_t " <<
s_start <<
" = " << fStartDims[i] <<
";\n";
434 out <<
SP <<
"if (" <<
s_start <<
" < 0) " <<
s_start <<
" += " << fShapeInput[fAxes[i]] <<
";\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";
440 out <<
SP <<
"if (" <<
s_start <<
" > " << fShapeInput[fAxes[i]] <<
" - 1" <<
" ) " <<
s_start <<
" = " << fShapeInput[fAxes[i]] <<
" - 1;\n";
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" };
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);
453 s_end = fEndDims[i].param;
454 out <<
SP <<
"size_t " <<
s_end <<
" = tensor_" << fNames[1] <<
"[" << i <<
"];\n";
456 out <<
SP <<
"size_t " <<
s_end <<
" = " << fEndDims[i] <<
";\n";
457 fEnd[fAxes[i]] =
s_end;
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";
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";
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" };
476 out <<
SP <<
"size_t iOut = 0;\n";
477 std::string
MSP =
SP;
479 out <<
MSP <<
"for (size_t i" <<
idim <<
" = " << fStart[
idim] <<
"; i" <<
idim <<
" < " << fEnd[
idim]
480 <<
"; i" <<
idim <<
"+= " << fSteps[
idim] <<
") {\n";
482 if (
idim < ndim-1) out <<
MSP <<
"size_t stride" <<
idim <<
" = " << strides[
idim] <<
"*i" <<
idim <<
";\n";
484 out <<
MSP <<
"size_t iInput = ";
485 for (
size_t idim = 0;
idim < ndim-1;
idim++) out <<
" stride" <<
idim <<
" + ";
487 out <<
"i" << ndim-1 <<
";\n";
488 out <<
MSP <<
"tensor_" << fNOutput <<
"[iOut++] = tensor_" <<fNData <<
"[iInput];\n";
490 MSP =
MSP.replace(0,
SP.length(),
"");