1#ifndef TMVA_SOFIE_ROPERATOR_SLICE
2#define TMVA_SOFIE_ROPERATOR_SLICE
13namespace Experimental{
18template <
typename IType>
58 for (
size_t i = 0; i < names.size(); ++i) {
79 throw std::runtime_error(
"TMVA Slice Op Input Tensor is not found in model");
82 std::vector<std::vector<Dim>> shapes;
86 std::vector<std::vector<IType>>
itensors(4);
90 for (
size_t i = 0; i < 4; ++i) {
112 for (
size_t k = 0; k < s; k++) {
147 for (
size_t i = 0; i <
fAxes.size(); i++) {
151 throw std::runtime_error(
"TMVA Slice Op : invalid axis value " + std::to_string(
fAxes[i]) +
152 " for " + std::to_string(i));
156 for (
size_t i = 0; i <
fAxes.size(); i++) {
160 throw std::runtime_error(
"TMVA Slice Op : Missing start input tensor");
165 throw std::runtime_error(
"TMVA Slice Op : Missing end input tensor");
191 throw std::runtime_error(
"TMVA Slice Op : parametric step inputs are not supported");
201 }
else if (
istep < 0) {
206 throw std::runtime_error(
"TMVA Slice Op : invalid step value " + std::to_string(
istep) +
207 " for " + std::to_string(i));
237 std::string send = std::string(
"(") +
fShapeInput[
fAxes[i]].param +
"-" + std::to_string(-
iend) +
")";
239 }
else if (
iend == std::numeric_limits<IType>::max()){
253 fShapeOutput.resize(dim);
254 for (
size_t i = 0; i < dim; i++) {
255 if (!fEnd[i].isParam && !fStart[i].isParam && !fSteps[i].isParam) {
256 int64_t
istart =
static_cast<int64_t
>(fStart[i].dim);
257 int64_t
iend =
static_cast<int64_t
>(fEnd[i].dim);
258 int64_t
istep=
static_cast<int64_t
>(fSteps[i].dim);
260 fShapeOutput[i] = Dim{
static_cast<size_t>(s)};
263 if (fStart[i].GetVal() !=
"0")
264 s =
"(" + fEnd[i].GetVal() +
"-" + fStart[i].GetVal() +
")";
266 s = fEnd[i].GetVal();
267 if (fSteps[i].GetVal() !=
"1") {
269 s +=
")/" + fSteps[i].GetVal() +
")";
271 fShapeOutput[i] = Dim{s,size_t(-1)};
274 if (fEnd[i].isParam && fEnd[i].dim !=
size_t(-1))
275 model.AddShapeParam(fEnd[i].param,fEnd[i].dim );
276 if (fStart[i].isParam && fStart[i].dim !=
size_t(-1))
277 model.AddShapeParam(fStart[i].param,fStart[i].dim );
278 if (fSteps[i].isParam && fSteps[i].dim !=
size_t(-1))
279 model.AddShapeParam(fSteps[i].param,fSteps[i].dim );
284 if (model.IsInitializedTensor(fNData) && model.GetTensorType(fNData) ==
ETensorType::INT64) {
285 fIsOutputConstant =
true;
286 auto inputData =
static_cast<int64_t*
>(model.GetInitializedTensorData(fNData).get());
291 std::cout <<
" start - end -steps \n";
292 for (
size_t ii = 0;
ii< fStart.size();
ii++)
293 std::cout << fStart[
ii] <<
" " << fEnd[
ii] <<
" " << fSteps[
ii] << std::endl;
297 std::cout <<
"SLice_impl " << fStart.size() <<
" " << fEnd.size() <<
" " << fSteps.size() <<
" " <<
iax << std::endl;
298 if (fStart[
iax].isParam || fEnd[
iax].isParam || fSteps[
iax].isParam)
299 throw std::runtime_error(
"TMVA Slice Op : cannot have parametric values when input is constant");
301 std::vector<IType> indices;
303 indices.push_back(i);
305 std::cout <<
"SLice_impl last axis: " << indices.size() <<
" : ";
306 for (
size_t i = 0; i < indices.size(); i++) {
311 std::cout << std::endl;
314 std::cout <<
"SLice_impl else : " << indices.size() <<
" : ";
315 for (
size_t i = 0; i < indices.size(); i++) {
320 std::cout << std::endl;
330 if (model.Verbose()) {
331 std::cout <<
"Slice: output is a constant tensor " <<
ConvertShapeToString(fShapeOutput) <<
" : "
337 size_t ndim = fShapeInput.size();
338 fIdentitySlice = fShapeOutput.size() == ndim;
340 fIdentitySlice &= !model.IsReadyInputTensor(fNData);
342 if (!fIdentitySlice)
break;
343 fIdentitySlice &= (fStart[
idim].GetVal() ==
"0");
344 fIdentitySlice &= (fSteps[
idim].GetVal() ==
"1");
345 fIdentitySlice &= (fEnd[
idim].GetVal() == fShapeOutput[
idim].GetVal());
348 model.AddIntermediateTensor(fNOutput, model.GetTensorType(fNData), fShapeOutput);
349 if (fIdentitySlice) model.AddAliasTensor(fNOutput, fNData);
351 if (model.Verbose()) {
354 if (fIdentitySlice) std::cout <<
" (using alias tensor since slice is an identity) ";
355 std::cout << std::endl;
363 if (fShapeInput.empty() || fShapeOutput.empty()){
364 throw std::runtime_error(
"TMVA SOFIE Slice Op called to Generate without being initialized first");
367 std::stringstream out;
369 out <<
"///------- Slice operator " <<
opName <<
"---> " << fNOutput <<
" "
371 if (fIsOutputConstant)
return out.str();
373 size_t ndim = fShapeInput.size();
375 if (fIdentitySlice) {
376 out <<
"/// Slice is just an identity (copy pointers) \n";
377 out << SP <<
"tensor_" << fNOutput <<
" = tensor_" << fNData <<
";\n";
382 auto strides = UTILITY::ComputeStrideFromShape(fShapeInput);
386 for (
size_t i = 0; i < fStepDims.size(); i++) {
387 if (fStepDims[i].isParam) {
389 out << SP <<
"size_t " << fStepDims[i] <<
" = tensor_" << fNames[3] <<
"[" << i <<
"];\n";
393 for (
size_t i = 0; i < fStartDims.size(); i++) {
394 if (fStartDims[i].isParam && fStartDims[i].param != fShapeInput[fAxes[i]].param) {
395 std::string
s_start =
"start_" + std::to_string(i);
398 out << SP <<
"size_t " <<
s_start <<
" = tensor_" << fNames[0] <<
"[" << i <<
"];\n";
400 out << SP <<
"size_t " <<
s_start <<
" = " << fStartDims[i] <<
";\n";
403 out << SP <<
"if (" <<
s_start <<
" < 0) " <<
s_start <<
" += " << fShapeInput[fAxes[i]] <<
";\n";
404 out << SP <<
"if (" <<
s_start <<
" < 0) " <<
s_start <<
" = 0;\n";
405 if (!fStepDims[i].isParam) {
406 if (
static_cast<IType>(fStepDims[i].dim) > 0 )
407 out << SP <<
"if (" <<
s_start <<
" > " << fShapeInput[fAxes[i]] <<
" ) " <<
s_start <<
" = " << fShapeInput[fAxes[i]] <<
";\n";
409 out << SP <<
"if (" <<
s_start <<
" > " << fShapeInput[fAxes[i]] <<
" - 1" <<
" ) " <<
s_start <<
" = " << fShapeInput[fAxes[i]] <<
" - 1;\n";
413 else if (fStartDims[i].isParam && fStartDims[i].param == fShapeInput[fAxes[i]].param && !fStepDims[i].isParam &&
static_cast<IType>(fStepDims[i].dim) < 0 ) {
414 fStart[fAxes[i]] =
Dim{ fStartDims[i].param +
"-1" };
418 for (
size_t i = 0; i < fEndDims.size(); i++) {
419 if (fEndDims[i].isParam && fEndDims[i].param != fShapeInput[fAxes[i]].param) {
420 std::string
s_end =
"end_" + std::to_string(i);
422 s_end = fEndDims[i].param;
423 out << SP <<
"size_t " <<
s_end <<
" = tensor_" << fNames[1] <<
"[" << i <<
"];\n";
425 out << SP <<
"size_t " <<
s_end <<
" = " << fEndDims[i] <<
";\n";
426 fEnd[fAxes[i]] =
s_end;
428 out << SP <<
"if (" <<
s_end <<
" < 0) " <<
s_end <<
" += " << fShapeInput[fAxes[i]] <<
";\n";
429 if (!fStepDims[i].isParam) {
430 if (
static_cast<IType>(fStepDims[i].dim) > 0 ) {
431 out << SP <<
"if (" <<
s_end <<
" < 0) " <<
s_end <<
" = 0;\n";
432 out << SP <<
"if (" <<
s_end <<
" > " << fShapeInput[fAxes[i]] <<
" ) " <<
s_end <<
" = " << fShapeInput[fAxes[i]] <<
";\n";
434 out << SP <<
"if (" <<
s_end <<
" < -1) " <<
s_end <<
" = -1;\n";
435 out << SP <<
"if (" <<
s_end <<
" > " << fShapeInput[fAxes[i]] <<
" - 1" <<
" ) " <<
s_end <<
" = " << fShapeInput[fAxes[i]] <<
" - 1;\n";
440 else if (fEndDims[i].isParam && fEndDims[i].param == fShapeInput[fAxes[i]].param && !fStepDims[i].isParam &&
static_cast<IType>(fStepDims[i].dim) < 0 ) {
441 fEnd[fAxes[i]] =
Dim{ fEndDims[i].param +
"-1" };
445 out << SP <<
"size_t iOut = 0;\n";
446 std::string
MSP = SP;
448 out <<
MSP <<
"for (size_t i" <<
idim <<
" = " << fStart[
idim] <<
"; i" <<
idim <<
" < " << fEnd[
idim]
449 <<
"; i" <<
idim <<
"+= " << fSteps[
idim] <<
") {\n";
451 if (
idim < ndim-1) out <<
MSP <<
"size_t stride" <<
idim <<
" = " << strides[
idim] <<
"*i" <<
idim <<
";\n";
453 out <<
MSP <<
"size_t iInput = ";
454 for (
size_t idim = 0;
idim < ndim-1;
idim++) out <<
" stride" <<
idim <<
" + ";
456 out <<
"i" << ndim-1 <<
";\n";
457 out <<
MSP <<
"tensor_" << fNOutput <<
"[iOut++] = tensor_" <<fNData <<
"[iInput];\n";
459 MSP =
MSP.replace(0,SP.length(),
"");
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 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
std::vector< size_t > GetTensorShape(const std::string &name) const
std::vector< Dim > GetDimTensorShape(const std::string &name) const
bool CheckIfTensorAlreadyExist(std::string tensor_name)
bool IsShapeTensor(const std::string &name) const
check if a tensor is a shape tensor
bool IsInitializedTensor(const std::string &name) const
std::shared_ptr< void > GetInitializedTensorData(std::string tensor_name)
const std::vector< Dim > & GetShapeTensorValues(const std::string &tensor_name) const
std::vector< std::vector< IType > > fAttributes
std::vector< Dim > fEndDims
std::vector< Dim > fStart
std::vector< Dim > fShapeOutput
std::vector< Dim > fSteps
std::vector< Dim > fStartDims
std::vector< Dim > fShapeInput
std::vector< IType > fAxes
void Initialize(RModel &model) override
std::vector< Dim > fStepDims
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 > fNames
std::vector< std::string_view > fInputTensorNames
std::vector< std::string_view > fOutputTensorNames
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)
std::vector< size_t > ConvertShapeToInt(const std::vector< Dim > &shape)
Convert shape based on Dim to integer format.
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations