1#ifndef TMVA_SOFIE_ROPERATOR_CLIP
2#define TMVA_SOFIE_ROPERATOR_CLIP
57 T
fMin = std::numeric_limits<T>::lowest();
58 T
fMax = std::numeric_limits<T>::max();
77 std::string nameMin =
"",
78 std::string nameMax =
"")
81 fNMin(nameMin.empty() ?
"" :
UTILITY::Clean_name(nameMin)),
82 fNMax(nameMax.empty() ?
"" :
UTILITY::Clean_name(nameMax))
110 if (!model.CheckIfTensorAlreadyExist(
fNX))
111 throw std::runtime_error(
112 "TMVA SOFIE Clip Op Input Tensor " +
fNX +
" is not found in model");
115 if (model.IsDynamicTensor(
fNX)) {
124 if (!
fNMin.empty() && model.CheckIfTensorAlreadyExist(
fNMin)) {
126 if (model.IsInitializedTensor(
fNMin)) {
128 auto data =
static_cast<T*
>(model.GetInitializedTensorData(
fNMin).get());
131 model.SetNotWritableInitializedTensor(
fNMin);
137 if (!
fNMax.empty() && model.CheckIfTensorAlreadyExist(
fNMax)) {
139 if (model.IsInitializedTensor(
fNMax)) {
140 auto data =
static_cast<T*
>(model.GetInitializedTensorData(
fNMax).get());
143 model.SetNotWritableInitializedTensor(
fNMax);
151 model.AddIntermediateTensor(
fNY, model.GetTensorType(
fNX),
fShape);
153 if (model.Verbose()) {
154 std::cout <<
"Clip : " <<
fNX <<
" "
158 ? std::to_string(
fMin) :
fNMin +
"(runtime)");
161 ? std::to_string(
fMax) :
fNMax +
"(runtime)");
162 std::cout <<
" --> " <<
fNY <<
"\n";
166 model.AddNeededStdLib(
"algorithm");
167 model.AddNeededStdLib(
"limits");
176 OpName =
"op_" + OpName;
179 throw std::runtime_error(
180 "TMVA SOFIE Operator Clip called to Generate without being initialized first");
182 std::stringstream out;
183 out <<
SP <<
"\n//------ CLIP " << OpName <<
"\n";
195 std::string minExpr, maxExpr;
200 minExpr =
"tensor_" +
fNMin +
"[0]";
210 maxExpr =
"tensor_" +
fNMax +
"[0]";
217 auto tensorValue = [](
const std::string &
name,
const std::string & index) {
219 s <<
"tensor_" <<
name <<
"[" << index <<
"]";
224 out <<
SP <<
"for (int id = 0; id < " << length <<
" ; id++) {\n";
225 std::string firstExpr =
fHasMax ?
"std::min(" + maxExpr +
", " + tensorValue(
fNX,
"id") +
")" : tensorValue(
fNX,
"id");
226 std::string secondExpr =
fHasMin ?
"std::max(" + minExpr +
", " + firstExpr +
")" : firstExpr;
227 out <<
SP <<
SP << tensorValue(
fNY,
"id") <<
" = " << secondExpr <<
";\n";
238 std::ostringstream ss;
239 ss << std::setprecision(std::numeric_limits<T>::max_digits10) << val;
241 if (ss.str().find(
".") == std::string::npos) ss <<
".";
244 if (std::is_same<T, float>::value) ss <<
"f";
std::vector< Dim > fDimShape
ROperator_Clip(std::string nameX, std::string nameY, T minVal, T maxVal)
std::string Generate(std::string OpName) override
void Initialize(RModel &model) override
ROperator_Clip(std::string nameX, std::string nameY, std::string nameMin="", std::string nameMax="")
std::string ToStringHighPrec(T val) const
std::vector< size_t > fShape
std::vector< std::string_view > fInputTensorNames
const std::string SP
space used to correctly indent the generated C++ code
std::vector< std::string_view > fOutputTensorNames
std::vector< Dim > ConvertShapeToDim(const std::vector< size_t > &shape)
Convert shape from integer format to dynamic one (based on Dim).
std::string ConvertDimShapeToLength(const std::vector< Dim > &shape)
std::string ConvertShapeToString(const std::vector< size_t > &shape)
create variable transformations