1#ifndef TMVA_SOFIE_ROPERATOR_SLICE
2#define TMVA_SOFIE_ROPERATOR_SLICE
18template <
typename IType>
54 ROperator_Slice(std::string nameData, std::vector<std::string> names, std::string nameOutput)
60 for (
size_t i = 0; i < names.size(); ++i) {
68 ROperator_Slice(std::string nameData, std::vector<IType> starts, std::vector<IType> ends, std::vector<IType> axes, std::string nameOutput)
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) {
96 auto tensor =
static_cast<IType *
>(dptr.get());
98 assert(
vec.size() == 1);
99 itensors[i] = std::vector<IType>(tensor, tensor +
vec[0]);
114 for (
size_t k = 0; k < s; k++) {
144 if (itensors[2].empty()) {
149 for (
size_t i = 0; i <
fAxes.size(); 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));
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])});
162 throw std::runtime_error(
"TMVA Slice Op : Missing start input tensor");
164 if (!itensors[1].empty())
165 fEndDims.push_back(
Dim{
static_cast<size_t>(itensors[1][i])});
167 throw std::runtime_error(
"TMVA Slice Op : Missing end input tensor");
169 if (!itensors[3].empty()) {
170 fStepDims.push_back(
Dim{
static_cast<size_t>(itensors[3][i])});
180 istart =
static_cast<IType
>(
fStartDims[i].dim);
181 if (istart < 0) istart = iAxisDim + istart;
183 IType iend =
static_cast<IType
>(iAxisDim);
185 iend =
static_cast<IType
>(
fEndDims[i].dim);
186 if (iend < 0) iend = iAxisDim + iend;
191 istep =
static_cast<IType
>(
fStepDims[i].dim);
193 throw std::runtime_error(
"TMVA Slice Op : parametric step inputs are not supported");
198 if (istart < 0) istart = 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;
208 throw std::runtime_error(
"TMVA Slice Op : invalid step value " + std::to_string(istep) +
209 " for " + std::to_string(i));
226 IType istart =
static_cast<IType
>(
fStartDims[i].dim);
228 std::string sstart = std::string(
"(") +
fShapeInput[
fAxes[i]].param +
"-" + std::to_string(-istart) +
")";
237 IType iend =
static_cast<IType
>(
fEndDims[i].dim);
239 std::string send = std::string(
"(") +
fShapeInput[
fAxes[i]].param +
"-" + std::to_string(-iend) +
")";
241 }
else if (iend == std::numeric_limits<IType>::max()){
256 for (
size_t i = 0; i < dim; i++) {
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;
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() +
")";
276 if (
fEnd[i].isParam &&
fEnd[i].dim !=
size_t(-1))
290 std::vector<int64_t> outputData(outputSize);
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;
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) {
301 throw std::runtime_error(
"TMVA Slice Op : cannot have parametric values when input is constant");
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);
307 for (
size_t i = 0; i < indices.size(); i++) {
308 outputData[outputIdx] = inputData[inputOffset + indices[i]];
313 for (
size_t i = 0; i < indices.size(); i++) {
314 size_t offset = inputOffset + inputStride[iax]*indices[i];
315 sliceRecImpl(iax+1, outputIdx,
offset,sliceRecImpl);
319 slice_impl(iaxis, outIdx, inOffset,slice_impl);
323 sliceRecursive(0, idx,
offset);
338 if (outputData.empty()) {
348 std::vector<int64_t>
data(outputData.size());
349 std::copy(outputData.begin(), outputData.end(),
data.begin());
363 for (
size_t idim = 0; idim < ndim; idim++) {
376 if (
fIdentitySlice) std::cout <<
" (using alias tensor since slice is an identity) ";
377 std::cout << std::endl;
383 std::string
Generate(std::string opName)
override {
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 <<
" "
397 for (
int i = 0; i < static_cast<int>(
fShapeOutput[0].dim); i++) {
406 out <<
"/// Slice is just an identity (copy) \n";
417 for (
size_t i = 0; i <
fStepDims.size(); i++) {
420 out <<
SP <<
"size_t " <<
fStepDims[i] <<
" = tensor_" <<
fNames[3] <<
"[" << i <<
"];\n";
424 for (
size_t i = 0; i <
fStartDims.size(); i++) {
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";
435 out <<
SP <<
"if (" << s_start <<
" < 0) " << s_start <<
" = 0;\n";
437 if (
static_cast<IType
>(
fStepDims[i].dim) > 0 )
449 for (
size_t i = 0; i <
fEndDims.size(); i++) {
451 std::string s_end =
"end_" + std::to_string(i);
454 out <<
SP <<
"size_t " << s_end <<
" = tensor_" <<
fNames[1] <<
"[" << i <<
"];\n";
456 out <<
SP <<
"size_t " << s_end <<
" = " <<
fEndDims[i] <<
";\n";
459 out <<
SP <<
"if (" << s_end <<
" < 0) " << s_end <<
" += " <<
fShapeInput[
fAxes[i]] <<
";\n";
461 if (
static_cast<IType
>(
fStepDims[i].dim) > 0 ) {
462 out <<
SP <<
"if (" << s_end <<
" < 0) " << s_end <<
" = 0;\n";
465 out <<
SP <<
"if (" << s_end <<
" < -1) " << s_end <<
" = -1;\n";
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";
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";
489 for (
size_t idim = 0; idim < ndim; idim++) {
490 MSP = MSP.replace(0,
SP.length(),
"");
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
void AddShapeParam(const std::string &name, size_t def_value=0)
std::vector< size_t > GetTensorShape(const std::string &name) const
std::vector< Dim > GetDimTensorShape(const std::string &name) const
void AddIntermediateTensor(std::string tensor_name, ETensorType type, std::vector< Dim > dim_shape)
bool CheckIfTensorAlreadyExist(std::string tensor_name)
void AddConstantTensor(std::string tensor_name, ETensorType type, std::vector< std::size_t > shape, std::shared_ptr< void > data)
bool IsDimInputTensor(const std::string &name) const
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)
ETensorType GetTensorType(std::string name) const
const std::vector< Dim > & GetShapeTensorValues(const std::string &tensor_name) const
bool IsReadyInputTensor(const std::string &name) const
void AddShapeTensor(const std::string &name, const std::vector< Dim > &shapeValues, bool scalar=false)
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 > fOutputShapeData
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
bool fIsOutputParamShape
flag to identify of the output represents a parametric shape (can be known at compile time)
bool fIsOutputConstant
flag to identify if operator has a constant output (no need to generate code)
const std::string SP
space used to correctly indent the generated C++ code
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, 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