@@ -114,6 +114,8 @@ struct LiteralNode {
114114 {
115115 }
116116
117+ LiteralNode (LiteralNode const & other) = default ;
118+
117119 using var_t = LiteralValue::stored_type;
118120 var_t value;
119121 atype::type type = atype::NA;
@@ -132,6 +134,7 @@ struct BindingNode {
132134// / An expression tree node corresponding to binary or unary operation
133135struct OpNode {
134136 OpNode (BasicOp op_) : op{op_} {}
137+ OpNode (OpNode const & other) = default ;
135138 BasicOp op;
136139};
137140
@@ -147,6 +150,8 @@ struct PlaceholderNode : LiteralNode {
147150 }
148151 }
149152
153+ PlaceholderNode (PlaceholderNode const & other) = default ;
154+
150155 void reset (InitContext& context)
151156 {
152157 value = retrieve (context, name.data ());
@@ -156,6 +161,28 @@ struct PlaceholderNode : LiteralNode {
156161 LiteralNode::var_t (*retrieve)(InitContext&, char const *);
157162};
158163
164+ // / A placeholder node for parameters taken from an array
165+ struct ParameterNode : LiteralNode {
166+ ParameterNode (int index_ = -1 )
167+ : LiteralNode((float )0 ),
168+ index{index_}
169+ {
170+ }
171+
172+ ParameterNode (ParameterNode const &) = default ;
173+
174+ template <typename T>
175+ void reset (T value_, int index_ = -1 )
176+ {
177+ (*static_cast <LiteralNode*>(this )) = LiteralNode (value_);
178+ if (index_ > 0 ) {
179+ index = index_;
180+ }
181+ }
182+
183+ int index;
184+ };
185+
159186// / A conditional node
160187struct ConditionalNode {
161188};
@@ -178,6 +205,10 @@ struct Node {
178205 {
179206 }
180207
208+ Node (ParameterNode&& p) : self{std::forward<ParameterNode>(p)}, left{nullptr }, right{nullptr }, condition{nullptr }
209+ {
210+ }
211+
181212 Node (ConditionalNode op, Node&& then_, Node&& else_, Node&& condition_)
182213 : self{op},
183214 left{std::make_unique<Node>(std::forward<Node>(then_))},
@@ -196,16 +227,70 @@ struct Node {
196227 right{nullptr },
197228 condition{nullptr } {}
198229
230+ Node (Node const & other)
231+ : self{other.self },
232+ index{other.index }
233+ {
234+ if (other.left != nullptr ) {
235+ left = std::make_unique<Node>(*other.left );
236+ }
237+ if (other.right != nullptr ) {
238+ right = std::make_unique<Node>(*other.right );
239+ }
240+ if (other.condition != nullptr ) {
241+ condition = std::make_unique<Node>(*other.condition );
242+ }
243+ }
244+
199245 // / variant with possible nodes
200- using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode, ConditionalNode>;
246+ using self_t = std::variant<LiteralNode, BindingNode, OpNode, PlaceholderNode, ConditionalNode, ParameterNode >;
201247 self_t self;
202248 size_t index = 0 ;
203249 // / pointers to children
204- std::unique_ptr<Node> left;
205- std::unique_ptr<Node> right;
206- std::unique_ptr<Node> condition;
250+ std::unique_ptr<Node> left = nullptr ;
251+ std::unique_ptr<Node> right = nullptr ;
252+ std::unique_ptr<Node> condition = nullptr ;
207253};
208254
255+ // / helper struct used to parse trees
256+ struct NodeRecord {
257+ // / pointer to the actual tree node
258+ Node* node_ptr = nullptr ;
259+ size_t index = 0 ;
260+ explicit NodeRecord (Node* node_, size_t index_) : node_ptr(node_), index{index_} {}
261+ bool operator !=(NodeRecord const & rhs)
262+ {
263+ return this ->node_ptr != rhs.node_ptr ;
264+ }
265+ };
266+
267+ // / Tree-walker helper
268+ template <typename L>
269+ void walk (Node* head, L const & pred)
270+ {
271+ std::stack<NodeRecord> path;
272+ path.emplace (head, 0 );
273+ while (!path.empty ()) {
274+ auto & top = path.top ();
275+ pred (top.node_ptr );
276+
277+ auto * leftp = top.node_ptr ->left .get ();
278+ auto * rightp = top.node_ptr ->right .get ();
279+ auto * condp = top.node_ptr ->condition .get ();
280+ path.pop ();
281+
282+ if (leftp != nullptr ) {
283+ path.emplace (leftp, 0 );
284+ }
285+ if (rightp != nullptr ) {
286+ path.emplace (rightp, 0 );
287+ }
288+ if (condp != nullptr ) {
289+ path.emplace (condp, 0 );
290+ }
291+ }
292+ }
293+
209294// / overloaded operators to build the tree from an expression
210295
211296#define BINARY_OP_NODES (_operator_, _operation_ ) \
@@ -402,6 +487,47 @@ inline Node ifnode(Node&& condition_, Configurable<L1> const& then_, Configurabl
402487 return Node{ConditionalNode{}, PlaceholderNode{then_}, PlaceholderNode{else_}, std::forward<Node>(condition_)};
403488}
404489
490+ // / Parameters
491+ inline Node par (int index)
492+ {
493+ return Node{ParameterNode{index}};
494+ }
495+
496+ // / binned functional
497+ template <typename T>
498+ inline Node binned (std::vector<T> const & binning, std::vector<T> const & parameters, Node&& binned, Node&& pexp, Node&& out)
499+ {
500+ int bins = binning.size () - 1 ;
501+ const auto binned_copy = binned;
502+ const auto out_copy = out;
503+ auto root = ifnode (Node{binned_copy} < binning[0 ], Node{out_copy}, LiteralNode{-1 });
504+ root.right = std::make_unique<Node>(ifnode (Node{binned_copy} > binning[0 ] && Node{binned_copy} <= binning [1 ], updateParameters (pexp, bins, parameters, 0 ), LiteralNode{-1 }));
505+ auto * current = root.right .get ();
506+ for (auto i = 1 ; i < bins; ++i) {
507+ current->right = std::make_unique<Node>(ifnode (Node{binned_copy} <= binning[i + 1 ], updateParameters (pexp, bins, parameters, i), LiteralNode{-1 }));
508+ current = current->right .get ();
509+ }
510+ current->right = std::make_unique<Node>(out);
511+
512+ return root;
513+ }
514+
515+ template <typename T>
516+ Node updateParameters (Node const & pexp, int bins, std::vector<T> const & parameters, int bin)
517+ {
518+ Node result{pexp};
519+ auto updateParameter = [&bins, ¶meters, &bin](Node* node)
520+ {
521+ if (node->self .index () == 5 ) {
522+ auto * n = std::get_if<5 >(&node->self );
523+ n->reset (parameters[bin * bins + n->index ]);
524+ }
525+ };
526+ walk (&result, updateParameter);
527+ return result;
528+ }
529+
530+
405531// / A struct, containing the root of the expression tree
406532struct Filter {
407533 Filter () = default ;
0 commit comments