diff --git a/src/feature_creation/node/FeatureNode.hpp b/src/feature_creation/node/FeatureNode.hpp
index 8d6db1ee1f9e64dfa87afa96bd07b5f89a24f8c7..8537d57248b9ee7f94b6b64d54f351fae6ecaaea 100644
--- a/src/feature_creation/node/FeatureNode.hpp
+++ b/src/feature_creation/node/FeatureNode.hpp
@@ -10,9 +10,6 @@
 
 #include <feature_creation/node/Node.hpp>
 
-typedef std::function<double(double)> unary_op_func;
-typedef std::function<double(double, double)> binary_op_func;
-
 /**
  * @brief Node that describe the leaves of the operator graph (Initial features in Phi_0)
  */
@@ -60,22 +57,7 @@ public:
     /**
      * @brief Set the value for the feature
      */
-    inline void set_value(){return;}
-
-    /**
-     * @brief Access the rung of the feature (Depth of the chart)
-     */
-    inline int rung(){return 0;}
-
-    /**
-     * @brief Set up the feature value pointers
-     */
-    inline void set_feat_val_ptrs(){return;}
-
-    /**
-     * @brief Accessor function to the feature value pointers
-     */
-    inline std::vector<double*> feat_value_ptrs(){return std::vector<double*>(0);}
+    inline void set_value(int offset = -1){return;}
 
     /**
      * @brief Check if the feature contains NaN
@@ -99,7 +81,12 @@ public:
     /**
      * @brief Accessor function to the value of the feature
      */
-    inline double* value_ptr(){return node_value_arrs::get_value_ptr(_feat_ind);}
+    inline double* value_ptr(int offset = 0){return node_value_arrs::get_value_ptr(_feat_ind, offset);}
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return cur_rung;}
 
     /**
      * @brief Serialization function to send over MPI
diff --git a/src/feature_creation/node/Node.hpp b/src/feature_creation/node/Node.hpp
index da370a645f4fb88baadc2573d70ee3712efae1e0..35b2e9416eb490ed820ee810a4a3521db0720e4a 100644
--- a/src/feature_creation/node/Node.hpp
+++ b/src/feature_creation/node/Node.hpp
@@ -14,9 +14,6 @@
 #include <boost/serialization/string.hpp>
 #include <boost/serialization/unique_ptr.hpp>
 
-typedef std::function<double(double)> unary_op_func;
-typedef std::function<double(double, double)> binary_op_func;
-
 /**
  * @brief Base class for a Node
  * @details Class used to describe a Node on the descriptor graph. Features are treated as an operation graph, these are the nodes on that graph.
@@ -73,27 +70,12 @@ public:
     /**
      * @brief Set the value for the feature
      */
-    virtual void set_value() = 0;
-
-    /**
-     * @brief Access the rung of the feature (Depth of the chart)
-     */
-    virtual int rung() = 0;
-
-    /**
-     * @brief Set up the feature value pointers
-     */
-    virtual void set_feat_val_ptrs() = 0;
-
-    /**
-     * @brief Accessor function to the feature value pointers
-     */
-    virtual std::vector<double*> feat_value_ptrs() = 0;
+    virtual void set_value(int offset = -1) = 0;
 
     /**
      * @brief Accessor function to the value of the feature
      */
-    virtual double* value_ptr() = 0;
+    virtual double* value_ptr(int offset = 0) = 0;
 
     /**
      * @brief Check if the feature contains NaN
@@ -110,6 +92,11 @@ public:
      */
     virtual NODE_TYPE type() = 0;
 
+    /**
+     * @brief return the rung of the feature
+     */
+    virtual int rung(int cur_rung = 0) = 0;
+
     /**
      * @brief Serialization function to send over MPI
      *
diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.cpp b/src/feature_creation/node/operator_nodes/OperatorNode.cpp
index ff1808cab47411381ce0ec3c8ba83f01f73a4ebe..0a9f7cb7b5e26dc76738b5551664e952c52379df 100644
--- a/src/feature_creation/node/operator_nodes/OperatorNode.cpp
+++ b/src/feature_creation/node/operator_nodes/OperatorNode.cpp
@@ -5,17 +5,28 @@ OperatorNode::OperatorNode()
 
 OperatorNode::OperatorNode(std::vector<node_ptr> feats, int rung, int feat_ind) :
     Node(feat_ind, feats[0]->n_samp()),
-    _rung_offset(rung),
     _feats(feats)
 {
-    set_feat_val_ptrs();
+    _feats.reserve(_feats.size());
 }
 
 OperatorNode::OperatorNode(const OperatorNode &o) :
     Node(o),
-    _rung_offset(o._rung_offset),
-    _feats(o._feats),
-    _feat_val_ptrs(o._feat_val_ptrs)
-{}
+    _feats(o._feats)
+{
+    _feats.reserve(_feats.size());
+}
+
+double* OperatorNode::value_ptr(int offset)
+{
+    offset = (offset == -1) ? rung() : offset;
+    if((rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feat_ind, offset) != _feat_ind))
+    {
+        set_value(offset);
+        node_value_arrs::temp_storage_reg(_feat_ind, offset) = _feat_ind;
+    }
+
+    return node_value_arrs::get_value_ptr(_feat_ind, offset);
+}
 
 BOOST_SERIALIZATION_ASSUME_ABSTRACT(OperatorNode)
diff --git a/src/feature_creation/node/operator_nodes/OperatorNode.hpp b/src/feature_creation/node/operator_nodes/OperatorNode.hpp
index 1a3825b407d9eaf5ce4b0d1623d2f1f3162deaf2..6cd8f4244e15fc4ef817ccc17978bb10e1ef0ca5 100644
--- a/src/feature_creation/node/operator_nodes/OperatorNode.hpp
+++ b/src/feature_creation/node/operator_nodes/OperatorNode.hpp
@@ -20,10 +20,7 @@ class OperatorNode: public Node
 {
     friend class boost::serialization::access;
 protected:
-    double* _value_ptr;
-    int _rung_offset;
     std::vector<node_ptr> _feats;
-    std::vector<double*> _feat_val_ptrs;
 
 public:
     /**
@@ -51,37 +48,24 @@ public:
 
     virtual Unit unit() = 0;
 
-    virtual void set_value() =0;
+    virtual void set_value(int offset = -1) = 0;
 
     template <typename Archive>
     void serialize(Archive& ar, const unsigned int version)
     {
         ar & boost::serialization::base_object<Node>(*this);
-        ar & _rung_offset;
         ar & _feats;
-        set_feat_val_ptrs();
     }
 
     /**
-     * @brief Accessor function to the feature value pointers
-     */
-    inline std::vector<double*> feat_value_ptrs(){return _feat_val_ptrs;}
-
-    /**
-     * @brief Access the rung of the feature (Depth of the chart)
+     * @brief Get the pointer to the feature's data
+     * @details If the feature is not already stored in memory, then calculate the feature and return the pointer to the data
+     *
+     * @param offset the integer value to offset the location in the temporary storage array
+     *
+     * @return pointer to the feature's value
      */
-    inline int rung(){return _rung_offset;}
-
-    /**
-     * @brief Accessor function to the value of the feature
-     */
-    inline double* value_ptr()
-    {
-        if((_rung_offset > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feat_ind) != _feat_ind))
-            set_value();
-
-        return node_value_arrs::get_value_ptr(_feat_ind);
-    }
+    double* value_ptr(int offset=-1);
 
     /**
      * @brief Check if the feature contains NaN
@@ -98,20 +82,14 @@ public:
     }
 
     /**
-     * @brief Returns the type of node this is
+     * @brief return the rung of the feature
      */
-    virtual NODE_TYPE type() = 0;
+    virtual int rung(int cur_rung = 0) = 0;
 
     /**
-     * @brief Set up the feature value pointers
+     * @brief Returns the type of node this is
      */
-    inline void set_feat_val_ptrs()
-    {
-        _value_ptr = node_value_arrs::get_value_ptr(_feat_ind, 0);
-        _feat_val_ptrs = std::vector<double*>(_feats.size());
-        for(int ff = 0; ff < _feats.size(); ++ff)
-            _feat_val_ptrs[ff] = node_value_arrs::get_value_ptr(_feats[ff]->feat_ind(), (_rung_offset + 2 - ff) % 3);
-    }
+    virtual NODE_TYPE type() = 0;
 };
 
 #endif
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
index c0590ee18af3f446e1e2e152da82a0a8295e6012..2453e9a40766ddf29ee380208c80e2ff20b96553 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.cpp
@@ -32,16 +32,3 @@ AbsDiffNode::AbsDiffNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_in
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void AbsDiffNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    if((_feats[1]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) != _feats[1]->feat_ind()))
-    {
-        std::copy_n(_feats[1]->value_ptr(), _n_samp, _feat_val_ptrs[1]);
-        node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) = _feats[1]->feat_ind();
-    }
-    allowed_op_funcs::abs_diff(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
index 0d3ec143a7a71039d048136e5d00e8a3bfa6db29..4ce38e04a77c11f669628ef26369f2870c827d8f 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_difference.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "|" + _feats[0]->expr() + " - (" + _feats[1]->expr() + ")|";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::abs_diff(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return std::max(_feats[0]->rung(cur_rung + 1), _feats[1]->rung(cur_rung + 1));}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
index 71f35c943a071f42ab12e8f128c4601e255b6ad0..4426869a25a6c1d7cb8436cc6551a4e46d0ec56e 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.cpp
@@ -20,11 +20,3 @@ AbsNode::AbsNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void AbsNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::abs(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
index 20afc8c52d9c5075547785e16e2fd7229be5b3ce..07523c4a6fddd9d03b71ab36f5a95c9af62d6429 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/absolute_value.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "|" + _feats[0]->expr() + "|";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::abs(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
index 1a75d051feb1728aea82172ab05d40120fecd875..a500268db7c78e31a0d19520929b07b68a520edc 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.cpp
@@ -24,16 +24,3 @@ AddNode::AddNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void AddNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    if((_feats[1]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) != _feats[1]->feat_ind()))
-    {
-        std::copy_n(_feats[1]->value_ptr(), _n_samp, _feat_val_ptrs[1]);
-        node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) = _feats[1]->feat_ind();
-    }
-    allowed_op_funcs::add(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
index faff638cfb1e3b932f41fe96c8ce6fe62895c3ca..6e496d05f920bc7584d97d51f61fd769cdbe7f57 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/add.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "(" + _feats[0]->expr() + " + " + _feats[1]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::add(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return std::max(_feats[0]->rung(cur_rung + 1), _feats[1]->rung(cur_rung + 1));}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
index 07d40fb1f319fdaaf628fba1e60f8ad7befed935..954d858b3636f816fe0609b07890bcb5ef1818cb 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.cpp
@@ -30,11 +30,3 @@ CosNode::CosNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void CosNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::cos(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
index bd246c745632e8827ee97989a31e4193ce157d43..29fa37531ad8e446209cf2c5aef2dc2a46320e35 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cos.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "cos(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::cos(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
index 72cd11c9c41501b0d64a4673d2ef1fbc0e032e2d..e5d652d340a6b50fb10facb3e95b77850359329b 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.cpp
@@ -24,11 +24,3 @@ CbNode::CbNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void CbNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::cb(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
index 671d7312a268236479ce488c12daaf1a899bdf57..3bad615dd54991c2a9037377e98b25c0c62105f5 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "(" + _feats[0]->expr() + ")^3";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::cb(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
index 18ab351a758bcf6b6a76704378545c2a73c2ca0e..21eb0e8b566056cd4d89a24d122df96589b3014b 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.cpp
@@ -24,11 +24,3 @@ CbrtNode::CbrtNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void CbrtNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::cbrt(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
index 88f0e9353944fa71afe218292c8f2b4967f71ea0..fa78ec94089efc352226bfda621c98bac391019f 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/cube_root.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "cbrt(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::cbrt(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
index 2fcd1955043f72261d2fbdc172795afbb7449a51..b116cc12264e5a51d6b68448b305327c85b778b4 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.cpp
@@ -24,16 +24,3 @@ DivNode::DivNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void DivNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    if((_feats[1]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) != _feats[1]->feat_ind()))
-    {
-        std::copy_n(_feats[1]->value_ptr(), _n_samp, _feat_val_ptrs[1]);
-        node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) = _feats[1]->feat_ind();
-    }
-    allowed_op_funcs::div(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
index 08607cc847b87b2bcf9cd25460cb7f9074e419f6..755acd61904ba1ce039b4c47b4988da318597f18 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/divide.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "[(" + _feats[0]->expr() + ") / (" + _feats[1]->expr() + ")]";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::div(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return std::max(_feats[0]->rung(cur_rung + 1), _feats[1]->rung(cur_rung + 1));}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
index ed2450d69fb893c9d5077576490ae535a58e8273..3a6f47ae712a15273725592b22042c7469b2ddaa 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.cpp
@@ -30,11 +30,3 @@ ExpNode::ExpNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void ExpNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::exp(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
index 46eb66c428c5ac45ff5724693106f4b538120909..605bd4f04fb93894aed26470c9bcd3611b0bc09c 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/exponential.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "exp(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::exp(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
index e33471a12ae5c35f6cd731cfc2b5fbc427815e6b..1cfe5f501b29cd59d7ec05fe6383133c19422b66 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.cpp
@@ -24,11 +24,3 @@ InvNode::InvNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void InvNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::inv(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
index 6bd02488feb01f600aa160b9129c618820cdceee..4f2c24b2263c05b3d16dbc92663229123c56cb8d 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/inverse.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "1.0 / (" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::inv(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
index 2a3e77e2156d24bf38989db31b6436ee9eab6c8c..6196fcd413519439c80e4e6ae67b3ee0d9fd7065 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.cpp
@@ -30,11 +30,3 @@ LogNode::LogNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void LogNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::log(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
index db792788c06436b7789d6aba37c3f976c8e0f6a8..8ba84f86828ae282d84f940322406c8ceb3f617c 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/log.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "log(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::log(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
index 66729c8070977eff9ad5daebeb859c885544f005..7e3b23cda6d5f01a7e2b719767b2bd8c73259f44 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.cpp
@@ -19,16 +19,3 @@ MultNode::MultNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind):
         throw InvalidFeatureException();
 }
 
-void MultNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    if((_feats[1]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) != _feats[1]->feat_ind()))
-    {
-        std::copy_n(_feats[1]->value_ptr(), _n_samp, _feat_val_ptrs[1]);
-        node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) = _feats[1]->feat_ind();
-    }
-
-    allowed_op_funcs::mult(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
index 9460ac6fdd968d9ad75480f482ace94b3b92f965..aa93bbd9a4814b6e91df2ee52df42a4488186f23 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/multiply.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "[(" + _feats[0]->expr() + ") * (" + _feats[1]->expr() + ")]";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::mult(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return std::max(_feats[0]->rung(cur_rung + 1), _feats[1]->rung(cur_rung + 1));}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
index ac6ff99606c3203a7e5b6ba926392eb00512c50e..6cb67bb1f6cb75459f5ebfcecbf90fb613944d03 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.cpp
@@ -32,11 +32,3 @@ NegExpNode::NegExpNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void NegExpNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::neg_exp(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
index 129036fd26121c034a7d862c63aea1e53d36db76..32e4d7859c43cef9bc0284f09b21b44cf79d7f78 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/negative_exponential.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "exp[-1.0*(" + _feats[0]->expr() + ")]";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::neg_exp(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    };
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
index c9845a1e62d05628a32fcfe4de725d65532e386a..ceba2dded9d97bc8af0bca223313b7a0c6f15b32 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.cpp
@@ -30,11 +30,3 @@ SinNode::SinNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
  }
-
-void SinNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::sin(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
index 306381ccfea02e0bcc80b1fe8059ed9fc2ab7c02..d871a87e23ca804d2fa7125d1ffd0dda78459378 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sin.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "sin(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::sin(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
index e69e3195185f18386bc7de9e0aa6fcfc69c9ac91..3d1063d4e86181888d7633ba6763b21a0f3b035c 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.cpp
@@ -24,11 +24,3 @@ SixPowNode::SixPowNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void SixPowNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::sixth_pow(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
index 85062f99c9ad76aa52e5624fdb5feec246bb4e84..6c2535be438fe96704ebfd0ba2a49437933aec89 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/sixth_power.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "(" + _feats[0]->expr() + ")^6";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::sixth_pow(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
index 1fe69a5adecb01bf37911bd92a038b37a9adf5e9..082f9e30299ca761e554572455776e5a403a9e62 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.cpp
@@ -24,11 +24,3 @@ SqNode::SqNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void SqNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::sq(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
index 8ced543357f1a84d642e533cb7dbd7fc935f138b..93ed269c1e348ab486e5a870bc93cd9d4cfdede7 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "(" + _feats[0]->expr() + ")^2";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::sq(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
index 09673fd7f18a87a5d5ca6b54c1a22e3963bf5b44..0bbcaa9acf6666f5cd58443dc1e4efabe3a0a835 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.cpp
@@ -24,11 +24,3 @@ SqrtNode::SqrtNode(node_ptr feat, int rung, int feat_ind):
     if(is_nan() || is_const())
         throw InvalidFeatureException();
 }
-
-void SqrtNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    allowed_op_funcs::sqrt(_n_samp, _feat_val_ptrs, _value_ptr);
-}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
index ab93e8e1652751b74590254224cd524b3573b316..086328a428fa0484adb1e3a3944e06d539d5011e 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/square_root.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "sqrt(" + _feats[0]->expr() + ")";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::sqrt(_n_samp, _feats[0]->value_ptr(offset + 2), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung=0){return _feats[0]->rung(cur_rung + 1);}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
index 4b7e6c7dae7f3f22cf8542e51dd1a0b5ba25b4fb..9c98078ab4143bab73a91898b8a4f0c7e0173665 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.cpp
@@ -23,18 +23,4 @@ SubNode::SubNode(node_ptr feat_1, node_ptr feat_2, int rung, int feat_ind):
     set_value();
     if(is_nan() || is_const())
         throw InvalidFeatureException();
- }
-
-void SubNode::set_value()
-{
-    if((_feats[0]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[0]->feat_ind(), 2) != _feats[0]->feat_ind()))
-        _feats[0]->set_value();
-
-    if((_feats[1]->rung() > node_value_arrs::N_RUNGS_STORED) && (node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) != _feats[1]->feat_ind()))
-    {
-        std::copy_n(_feats[1]->value_ptr(), _n_samp, _feat_val_ptrs[1]);
-        node_value_arrs::temp_storage_reg(_feats[1]->feat_ind(), 1) = _feats[1]->feat_ind();
-    }
-
-    allowed_op_funcs::sub(_n_samp, _feat_val_ptrs, _value_ptr);
-}
\ No newline at end of file
+}
diff --git a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
index 5be24fe019a7a2770314d099ac5a0bf630462e7e..daa24450ba43d00c85f4fc55eda2cb6d79a12c68 100644
--- a/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
+++ b/src/feature_creation/node/operator_nodes/allowed_operator_nodes/subtract.hpp
@@ -17,7 +17,16 @@ public:
 
     inline std::string expr(){return "[(" + _feats[0]->expr() + ") - (" + _feats[1]->expr() + ")]";}
 
-    void set_value();
+    inline void set_value(int offset = -1)
+    {
+        offset = (offset == -1) ? rung() : offset;
+        allowed_op_funcs::sub(_n_samp, _feats[0]->value_ptr(offset + 2), _feats[1]->value_ptr(offset + 1), node_value_arrs::get_value_ptr(_feat_ind, offset));
+    }
+
+    /**
+     * @brief return the rung of the feature
+     */
+    inline int rung(int cur_rung = 0){return std::max(_feats[0]->rung(cur_rung + 1), _feats[1]->rung(cur_rung + 1));}
 
     /**
      * @brief Returns the type of node this is
diff --git a/src/feature_creation/node/operator_nodes/functions.hpp b/src/feature_creation/node/operator_nodes/functions.hpp
index ba31571c220a6ed84ce64b73e438828dd3e7194f..f14cd8eba09c042683baed998febf6f2ef269c27 100644
--- a/src/feature_creation/node/operator_nodes/functions.hpp
+++ b/src/feature_creation/node/operator_nodes/functions.hpp
@@ -4,8 +4,6 @@
 #include <algorithm>
 #include <functional>
 
-typedef std::function<void(int, std::vector<double*>&, double*)> op_func;
-
 namespace allowed_op_funcs
 {
     /**
@@ -15,9 +13,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void add(int size, std::vector<double*>& inputs, double* out)
+    inline void add(int size, double* in_0, double* in_1, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, inputs[1], out, std::plus<double>());
+        std::transform(in_0, in_0 + size, in_1, out, std::plus<double>());
     }
 
     /**
@@ -27,9 +25,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void sub(int size, std::vector<double*>& inputs, double* out)
+    inline void sub(int size, double* in_0, double* in_1, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, inputs[1], out, std::minus<double>());
+        std::transform(in_0, in_0 + size, in_1, out, std::minus<double>());
     }
 
     /**
@@ -39,9 +37,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void abs_diff(int size, std::vector<double*>& inputs, double* out)
+    inline void abs_diff(int size, double* in_0, double* in_1, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, inputs[1], out, [](double in_0, double in_1){return std::abs(in_0 - in_1);});
+        std::transform(in_0, in_0 + size, in_1, out, [](double in_0, double in_1){return std::abs(in_0 - in_1);});
     }
 
     /**
@@ -51,9 +49,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void mult(int size, std::vector<double*>& inputs, double* out)
+    inline void mult(int size, double* in_0, double* in_1, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, inputs[1], out, std::multiplies<double>());
+        std::transform(in_0, in_0 + size, in_1, out, std::multiplies<double>());
     }
 
     /**
@@ -63,9 +61,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void div(int size, std::vector<double*>& inputs, double* out)
+    inline void div(int size, double* in_0, double* in_1, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, inputs[1], out, std::divides<double>());
+        std::transform(in_0, in_0 + size, in_1, out, std::divides<double>());
     }
 
     /**
@@ -75,9 +73,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void exp(int size, std::vector<double*>& inputs, double* out)
+    inline void exp(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::exp(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::exp(in_0);});
     }
 
     /**
@@ -87,9 +85,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void neg_exp(int size, std::vector<double*>& inputs, double* out)
+    inline void neg_exp(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::exp(-1.0*in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::exp(-1.0*in_0);});
     }
 
     /**
@@ -99,9 +97,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void sq(int size, std::vector<double*>& inputs, double* out)
+    inline void sq(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::pow(in_0, 2.0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::pow(in_0, 2.0);});
     }
 
     /**
@@ -111,9 +109,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void cb(int size, std::vector<double*>& inputs, double* out)
+    inline void cb(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::pow(in_0, 3.0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::pow(in_0, 3.0);});
     }
 
     /**
@@ -123,9 +121,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void sixth_pow(int size, std::vector<double*>& inputs, double* out)
+    inline void sixth_pow(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::pow(in_0, 6.0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::pow(in_0, 6.0);});
     }
 
     /**
@@ -135,9 +133,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void cbrt(int size, std::vector<double*>& inputs, double* out)
+    inline void cbrt(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::pow(in_0, 1.0/3.0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::pow(in_0, 1.0/3.0);});
     }
 
     /**
@@ -147,9 +145,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void sqrt(int size, std::vector<double*>& inputs, double* out)
+    inline void sqrt(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::sqrt(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::sqrt(in_0);});
     }
 
     /**
@@ -159,9 +157,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void inv(int size, std::vector<double*>& inputs, double* out)
+    inline void inv(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return 1.0 / in_0;});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return 1.0 / in_0;});
     }
 
     /**
@@ -171,9 +169,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void log(int size, std::vector<double*>& inputs, double* out)
+    inline void log(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::log(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::log(in_0);});
     }
 
     /**
@@ -183,9 +181,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void sin(int size, std::vector<double*>& inputs, double* out)
+    inline void sin(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::sin(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::sin(in_0);});
     }
 
     /**
@@ -195,9 +193,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void cos(int size, std::vector<double*>& inputs, double* out)
+    inline void cos(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::cos(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::cos(in_0);});
     }
 
     /**
@@ -207,9 +205,9 @@ namespace allowed_op_funcs
      * @param inputs array of the pointers to the input arrays
      * @param out pointer to the output array
      */
-    inline void abs(int size, std::vector<double*>& inputs, double* out)
+    inline void abs(int size, double* in_0, double* out)
     {
-        std::transform(inputs[0], inputs[0] + size, out, [](double in_0){return std::abs(in_0);});
+        std::transform(in_0, in_0 + size, out, [](double in_0){return std::abs(in_0);});
     }
 };
 
diff --git a/src/feature_creation/node/value_storage/nodes_value_containers.hpp b/src/feature_creation/node/value_storage/nodes_value_containers.hpp
index daefbebad2d1202166eeab0b0c6035381aa0da5a..a5a096820014a02efbd6296772924a72179fedb1 100644
--- a/src/feature_creation/node/value_storage/nodes_value_containers.hpp
+++ b/src/feature_creation/node/value_storage/nodes_value_containers.hpp
@@ -56,7 +56,7 @@ namespace node_value_arrs
      *
      * @return The register element for a given feature index and offset
      */
-    inline int& temp_storage_reg(int ind, int offset = 0){return TEMP_STORAGE_REG[(ind % N_STORE_FEATURES) + offset * N_STORE_FEATURES];}
+    inline int& temp_storage_reg(int ind, int offset = 0){return TEMP_STORAGE_REG[(ind % N_STORE_FEATURES) + (offset % 3) * N_STORE_FEATURES];}
 
     /**
      * @brief Access element of the permanent storage array
@@ -89,7 +89,7 @@ namespace node_value_arrs
         if(ind < N_STORE_FEATURES)
             return  access_value_arr(ind);
         temp_storage_reg(ind, offset) = ind;
-        return access_temp_storage((ind % N_STORE_FEATURES) + offset * N_STORE_FEATURES);
+        return access_temp_storage((ind % N_STORE_FEATURES) + (offset % 3) * N_STORE_FEATURES);
     }
 }