C++ Mathematical Expression Library (ExprTk)  https://www.partow.net/programming/exprtk/index.html
diff --git a/exprtk.hpp b/exprtk.hpp
index dc5e775..b251333 100644
--- a/exprtk.hpp
+++ b/exprtk.hpp
@@ -4269,6 +4269,205 @@
          };
       }
 
+      #ifdef exprtk_enable_debugging
+      inline void dump_ptr(const std::string& s, const void* ptr)
+      {
+         exprtk_debug(("%s - addr: %p\n",s.c_str(),ptr));
+      }
+      #else
+      inline void dump_ptr(const std::string&, const void*) {}
+      #endif
+
+      template <typename T>
+      class vec_data_store
+      {
+      public:
+
+         typedef vec_data_store<T> type;
+         typedef T* data_t;
+
+      private:
+
+         struct control_block
+         {
+            control_block()
+            : ref_count(1),
+              size     (0),
+              data     (0),
+              destruct (false)
+            {}
+
+            control_block(const std::size_t& dsize)
+            : ref_count(1),
+              size     (dsize),
+              data     (0),
+              destruct (true)
+            { create_data(); }
+
+            control_block(const std::size_t& dsize, data_t dptr, bool dstrct = false)
+            : ref_count(1),
+              size     (dsize),
+              data     (dptr ),
+              destruct (dstrct)
+            {}
+
+           ~control_block()
+            {
+               if (data && destruct && (0 == ref_count))
+               {
+                  dump_ptr("~control_block() data",data);
+                  delete[] data;
+                  data = 0;
+               }
+            }
+
+            static inline control_block* create(const std::size_t& size, data_t data_ptr = data_t(0), bool dstrct = false)
+            {
+               if (size)
+               {
+                  if (0 == data_ptr)
+                     return new control_block(size);
+                  else
+                     return new control_block(size, data_ptr, dstrct);
+               }
+               else
+                  return new control_block;
+            }
+
+            static inline void destroy(control_block*& cntrl_blck)
+            {
+               if (cntrl_blck)
+               {
+                  if (
+                       (0 !=   cntrl_blck->ref_count) &&
+                       (0 == --cntrl_blck->ref_count)
+                     )
+                  {
+                     delete cntrl_blck;
+                  }
+
+                  cntrl_blck = 0;
+               }
+            }
+
+            std::size_t ref_count;
+            std::size_t size;
+            data_t      data;
+            bool        destruct;
+
+         private:
+
+            control_block(const control_block&);
+            control_block& operator=(const control_block&);
+
+            inline void create_data()
+            {
+               destruct = true;
+               data     = new T[size];
+               std::fill_n(data,size,T(0));
+               dump_ptr("control_block::create_data() - data: ",data);
+            }
+         };
+
+      public:
+
+         vec_data_store()
+         : control_block_(control_block::create(0))
+         {}
+
+         vec_data_store(const std::size_t& size, data_t data = data_t(0), bool dstrct = false)
+         : control_block_(control_block::create(size,data,dstrct))
+         {}
+
+         vec_data_store(const type& vds)
+         {
+            control_block_ = vds.control_block_;
+            control_block_->ref_count++;
+         }
+
+        ~vec_data_store()
+         {
+            control_block::destroy(control_block_);
+         }
+
+         type& operator=(const type& vds)
+         {
+            if (this != &vds)
+            {
+               std::size_t final_size = min_size(control_block_, vds.control_block_);
+
+               control_block::destroy(control_block_);
+
+               control_block_ = vds.control_block_;
+               control_block_->ref_count++;
+               control_block_->size = final_size;
+            }
+
+            return *this;
+         }
+
+         inline data_t data()
+         {
+            return control_block_->data;
+         }
+
+         inline data_t data() const
+         {
+            return control_block_->data;
+         }
+
+         inline std::size_t size()
+         {
+            return control_block_->size;
+         }
+
+         inline std::size_t size() const
+         {
+            return control_block_->size;
+         }
+
+         inline void dump() const
+         {
+            #ifdef exprtk_enable_debugging
+            exprtk_debug(("size: %d\taddress:%p\tdestruct:%c\n",
+                          size(),
+                          data(),
+                          (control_block_->destruct ? 'T' : 'F')));
+
+            for (std::size_t i = 0; i < size(); ++i)
+            {
+               if (5 == i)
+                  exprtk_debug(("\n"));
+
+               exprtk_debug(("%15.10f ",data()[i]));
+            }
+            exprtk_debug(("\n"));
+            #endif
+         }
+
+         static inline void match_sizes(type& vds0, type& vds1)
+         {
+            std::size_t size = min_size(vds0.control_block_,vds1.control_block_);
+            vds0.control_block_->size = size;
+            vds1.control_block_->size = size;
+         }
+
+      private:
+
+         static inline std::size_t min_size(control_block* cb0, control_block* cb1)
+         {
+            std::size_t size0 = cb0->size;
+            std::size_t size1 = cb1->size;
+
+            if (size0 && size1)
+               return std::min(size0,size1);
+            else
+               return (size0) ? size0 : size1;
+         }
+
+         control_block* control_block_;
+      };
+
       namespace numeric
       {
          namespace details
@@ -4839,10 +5038,16 @@
 
       public:
 
+         typedef typename details::vec_data_store<Type> vds_t;
+
          vector_holder(Type* vec, const std::size_t& vec_size)
          : vector_holder_base_(new(buffer)array_vector_impl(vec,vec_size))
          {}
 
+         vector_holder(const vds_t& vds)
+         : vector_holder_base_(new(buffer)array_vector_impl(vds.data(),vds.size()))
+         {}
+
          template <typename Allocator>
          vector_holder(std::vector<Type,Allocator>& vec)
          : vector_holder_base_(new(buffer)sequence_vector_impl<Allocator,std::vector>(vec))
@@ -6412,16 +6617,23 @@
       {
       public:
 
-         typedef vector_node<T>* vector_node_ptr;
+         typedef vector_node<T>*   vector_node_ptr;
+         typedef vec_data_store<T>           vds_t;
 
          virtual ~vector_interface()
          {}
 
+         virtual std::size_t size   () const = 0;
+
          virtual vector_node_ptr vec() const = 0;
 
          virtual vector_node_ptr vec() = 0;
 
-         virtual std::size_t size() const = 0;
+         virtual       vds_t& vds   ()       = 0;
+
+         virtual const vds_t& vds   () const = 0;
+
+         virtual bool side_effect   () const { return false; }
       };
 
       template <typename T>
@@ -6433,14 +6645,21 @@
          typedef expression_node<T>*  expression_ptr;
          typedef vector_holder<T>    vector_holder_t;
          typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>             vds_t;
 
          vector_node(vector_holder_t* vh)
-         : vector_holder_(vh)
+         : vector_holder_(vh),
+           vds_(ref().size(),ref()[0])
+         {}
+
+         vector_node(vector_holder_t* vh, const vds_t& vds)
+         : vector_holder_(vh),
+           vds_(vds)
          {}
 
          inline T value() const
          {
-            return *(ref()[0]);
+            return vds().data()[0];
          }
 
          inline const vector_holder_t& ref() const
@@ -6470,12 +6689,23 @@
 
          std::size_t size() const
          {
-            return ref().size();
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_holder_t* vector_holder_;
+         vds_t                      vds_;
       };
 
       template <typename T>
@@ -6676,8 +6906,9 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef expression_node<T>*  expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>             vds_t;
 
          swap_vecvec_node(expression_ptr branch0,
                           expression_ptr branch1)
@@ -6685,7 +6916,7 @@
            vec0_node_ptr_(0),
            vec1_node_ptr_(0),
            vec_size_     (0),
-           initialised_(false)
+           initialised_  (false)
          {
             if (is_ivector_node(binary_node<T>::branch_[0].first))
             {
@@ -6694,6 +6925,7 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
                {
                   vec0_node_ptr_ = vi->vec();
+                  vds()          = vi->vds();
                }
             }
 
@@ -6757,12 +6989,23 @@
             return vec_size_;
          }
 
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
+         }
+
       private:
 
          vector_node<T>* vec0_node_ptr_;
          vector_node<T>* vec1_node_ptr_;
          std::size_t     vec_size_;
          bool            initialised_;
+         vds_t           vds_;
       };
 
       #ifndef exprtk_disable_string_capabilities
@@ -8655,6 +8898,7 @@
             if (var_node_ptr_)
             {
                T& result = var_node_ptr_->ref();
+
                result = binary_node<T>::branch_[1].first->value();
 
                return result;
@@ -8692,6 +8936,7 @@
             if (vec_node_ptr_)
             {
                T& result = vec_node_ptr_->ref();
+
                result = binary_node<T>::branch_[1].first->value();
 
                return result;
@@ -8713,18 +8958,18 @@
 
          typedef expression_node<T>* expression_ptr;
          typedef vector_node<T>*    vector_node_ptr;
+         typedef vec_data_store<T>            vds_t;
 
          assignment_vec_node(const operator_type& opr,
                              expression_ptr branch0,
                              expression_ptr branch1)
          : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
+           vec_node_ptr_(0)
          {
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
-               vec_size_     = vec_node_ptr_->ref().size();
+               vds()         = vec_node_ptr_->vds();
             }
          }
 
@@ -8734,9 +8979,9 @@
             {
                const T v = binary_node<T>::branch_[1].first->value();
 
-               T* vec = vec_node_ptr_->ref().data();
+               T* vec = vds().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec + lud.upper_bound;
 
                while (vec < upper_bound)
@@ -8801,13 +9046,23 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
+         vds_t           vds_;
       };
 
       template <typename T>
@@ -8816,8 +9071,9 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef expression_node<T>*  expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>             vds_t;
 
          assignment_vecvec_node(const operator_type& opr,
                                 expression_ptr branch0,
@@ -8825,17 +9081,19 @@
          : binary_node<T>(opr,branch0,branch1),
            vec0_node_ptr_(0),
            vec1_node_ptr_(0),
-           vec_size_     (0),
-           initialised_(false)
+           initialised_(false),
+           src_is_ivec_(false)
          {
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vds()          = vec0_node_ptr_->vds();
             }
 
             if (is_vector_node(binary_node<T>::branch_[1].first))
             {
                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
             }
             else if (is_ivector_node(binary_node<T>::branch_[1].first))
             {
@@ -8844,28 +9102,33 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
                {
                   vec1_node_ptr_ = vi->vec();
+
+                  if (!vi->side_effect())
+                  {
+                     vi->vds()    = vds();
+                     src_is_ivec_ = true;
+                  }
+                  else
+                     vds_t::match_sizes(vds(),vi->vds());
                }
             }
 
-            if (vec0_node_ptr_ && vec1_node_ptr_)
-            {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
-
-               initialised_ = true;
-            }
+            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
          }
 
          inline T value() const
          {
-            binary_node<T>::branch_[1].first->value();
-
             if (initialised_)
             {
-               T* vec0 = vec0_node_ptr_->ref().data();
-               T* vec1 = vec1_node_ptr_->ref().data();
+               binary_node<T>::branch_[1].first->value();
 
-               loop_unroll::details lud(vec_size_);
+               if (src_is_ivec_)
+                  return vec0_node_ptr_->value();
+
+               T* vec0 = vec0_node_ptr_->vds().data();
+               T* vec1 = vec1_node_ptr_->vds().data();
+
+               loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
@@ -8931,15 +9194,26 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node<T>* vec0_node_ptr_;
          vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
          bool            initialised_;
+         bool            src_is_ivec_;
+         vds_t           vds_;
       };
 
       template <typename T, typename Operation>
@@ -9022,20 +9296,20 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef expression_node<T>*  expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>             vds_t;
 
          assignment_vec_op_node(const operator_type& opr,
                                 expression_ptr branch0,
                                 expression_ptr branch1)
          : binary_node<T>(opr,branch0,branch1),
-           vec_node_ptr_(0),
-           vec_size_    (0)
+           vec_node_ptr_(0)
          {
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
-               vec_size_     = vec_node_ptr_->ref().size();
+               vds()         = vec_node_ptr_->vds();
             }
          }
 
@@ -9045,9 +9319,9 @@
             {
                const T v = binary_node<T>::branch_[1].first->value();
 
-               T* vec = vec_node_ptr_->ref().data();
+               T* vec = vds().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec + lud.upper_bound;
 
                while (vec < upper_bound)
@@ -9112,13 +9386,28 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
+         }
+
+         bool side_effect() const
+         {
+            return true;
          }
 
       private:
 
          vector_node<T>* vec_node_ptr_;
-         std::size_t     vec_size_;
+         vds_t           vds_;
       };
 
       template <typename T, typename Operation>
@@ -9127,8 +9416,9 @@
       {
       public:
 
-         typedef expression_node<T>* expression_ptr;
+         typedef expression_node<T>*  expression_ptr;
          typedef vector_node<T>*     vector_node_ptr;
+         typedef vec_data_store<T>             vds_t;
 
          assignment_vecvec_op_node(const operator_type& opr,
                                    expression_ptr branch0,
@@ -9136,17 +9426,18 @@
          : binary_node<T>(opr,branch0,branch1),
            vec0_node_ptr_(0),
            vec1_node_ptr_(0),
-           vec_size_     (0),
            initialised_(false)
          {
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec0_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[0].first);
+               vds()          = vec0_node_ptr_->vds();
             }
 
             if (is_vector_node(binary_node<T>::branch_[1].first))
             {
                vec1_node_ptr_ = static_cast<vector_node<T>*>(binary_node<T>::branch_[1].first);
+               vec1_node_ptr_->vds() = vds();
             }
             else if (is_ivector_node(binary_node<T>::branch_[1].first))
             {
@@ -9155,16 +9446,13 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
                {
                   vec1_node_ptr_ = vi->vec();
+                  vec1_node_ptr_->vds() = vds();
                }
+               else
+                  vds_t::match_sizes(vds(),vec1_node_ptr_->vds());
             }
 
-            if (vec0_node_ptr_ && vec1_node_ptr_)
-            {
-               vec_size_ = std::min(vec0_node_ptr_->ref().size(),
-                                    vec1_node_ptr_->ref().size());
-
-               initialised_ = true;
-            }
+            initialised_ = (vec0_node_ptr_ && vec1_node_ptr_);
          }
 
          inline T value() const
@@ -9177,7 +9465,7 @@
                T* vec0 = vec0_node_ptr_->ref().data();
                T* vec1 = vec1_node_ptr_->ref().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
@@ -9245,15 +9533,30 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
+         }
+
+         bool side_effect() const
+         {
+            return true;
          }
 
       private:
 
          vector_node<T>* vec0_node_ptr_;
          vector_node<T>* vec1_node_ptr_;
-         std::size_t     vec_size_;
          bool            initialised_;
+         vds_t           vds_;
       };
 
       template <typename T, typename Operation>
@@ -9265,6 +9568,7 @@
          typedef expression_node<T>*    expression_ptr;
          typedef vector_node<T>*       vector_node_ptr;
          typedef vector_holder<T>*   vector_holder_ptr;
+         typedef vec_data_store<T>               vds_t;
 
          vec_binop_vecvec_node(const operator_type& opr,
                                expression_ptr branch0,
@@ -9272,12 +9576,13 @@
          : binary_node<T>(opr,branch0,branch1),
            vec0_node_ptr_(0),
            vec1_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
            temp_         (0),
            temp_vec_node_(0),
            initialised_(false)
          {
+            bool v0_is_ivec = false;
+            bool v1_is_ivec = false;
+
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
@@ -9289,6 +9594,7 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
                {
                   vec0_node_ptr_ = vi->vec();
+                  v0_is_ivec     = true;
                }
             }
 
@@ -9303,6 +9609,7 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
                {
                   vec1_node_ptr_ = vi->vec();
+                  v1_is_ivec     = true;
                }
             }
 
@@ -9311,10 +9618,15 @@
                vector_holder<T>& vec0 = vec0_node_ptr_->ref();
                vector_holder<T>& vec1 = vec1_node_ptr_->ref();
 
-               vec_size_      = std::min(vec0.size(),vec1.size());
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+               if (v0_is_ivec && (vec0.size() <= vec1.size()))
+                  vds_ = vds_t(vec0_node_ptr_->vds());
+               else if (v1_is_ivec && (vec1.size() <= vec0.size()))
+                  vds_ = vds_t(vec1_node_ptr_->vds());
+               else
+                  vds_ = vds_t(std::min(vec0.size(),vec1.size()));
+
+               temp_          = new vector_holder<T>(vds().data(),vds().size());
+               temp_vec_node_ = new vector_node<T>  (temp_,vds());
 
                initialised_ = true;
             }
@@ -9322,9 +9634,8 @@
 
         ~vec_binop_vecvec_node()
          {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
+            delete temp_;
+            delete temp_vec_node_;
          }
 
          inline T value() const
@@ -9336,9 +9647,9 @@
 
                T* vec0 = vec0_node_ptr_->ref().data();
                T* vec1 = vec1_node_ptr_->ref().data();
-               T* vec2 = (*temp_).data();
+               T* vec2 = vds().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec2 + lud.upper_bound;
 
                while (vec2 < upper_bound)
@@ -9384,7 +9695,7 @@
                #undef exprtk_loop
                #undef case_stmt
 
-               return ((*temp_).data())[0];
+               return (vds().data())[0];
             }
             else
                return std::numeric_limits<T>::quiet_NaN();
@@ -9407,18 +9718,27 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds_.size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node_ptr   vec0_node_ptr_;
          vector_node_ptr   vec1_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
          vector_holder_ptr temp_;
          vector_node_ptr   temp_vec_node_;
          bool              initialised_;
+         vds_t             vds_;
       };
 
       template <typename T, typename Operation>
@@ -9430,17 +9750,18 @@
          typedef expression_node<T>*    expression_ptr;
          typedef vector_node<T>*       vector_node_ptr;
          typedef vector_holder<T>*   vector_holder_ptr;
+         typedef vec_data_store<T>               vds_t;
 
          vec_binop_vecval_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
          : binary_node<T>(opr,branch0,branch1),
            vec0_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
            temp_         (0),
            temp_vec_node_(0)
          {
+            bool v0_is_ivec = false;
+
             if (is_vector_node(binary_node<T>::branch_[0].first))
             {
                vec0_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[0].first);
@@ -9452,25 +9773,26 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[0].first)))
                {
                   vec0_node_ptr_ = vi->vec();
+                  v0_is_ivec     = true;
                }
             }
 
             if (vec0_node_ptr_)
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               if (v0_is_ivec)
+                  vds_        = vec0_node_ptr_->vds();
+               else
+                  vds_        = vds_t(vec0_node_ptr_->size());
 
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_          = new vector_holder<T>(vds());
                temp_vec_node_ = new vector_node<T>  (temp_);
             }
          }
 
         ~vec_binop_vecval_node()
          {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
+            delete temp_;
+            delete temp_vec_node_;
          }
 
          inline T value() const
@@ -9481,9 +9803,9 @@
                const T v = binary_node<T>::branch_[1].first->value();
 
                T* vec0 = vec0_node_ptr_->ref().data();
-               T* vec1 = (*temp_).data();
+               T* vec1 = vds().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
@@ -9528,7 +9850,7 @@
                #undef exprtk_loop
                #undef case_stmt
 
-               return ((*temp_).data())[0];
+               return (vds().data())[0];
             }
             else
                return std::numeric_limits<T>::quiet_NaN();
@@ -9551,16 +9873,25 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node_ptr   vec0_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
          vector_holder_ptr temp_;
          vector_node_ptr   temp_vec_node_;
+         vds_t             vds_;
       };
 
       template <typename T, typename Operation>
@@ -9572,17 +9903,18 @@
          typedef expression_node<T>*    expression_ptr;
          typedef vector_node<T>*       vector_node_ptr;
          typedef vector_holder<T>*   vector_holder_ptr;
+         typedef vec_data_store<T>               vds_t;
 
          vec_binop_valvec_node(const operator_type& opr,
                                expression_ptr branch0,
                                expression_ptr branch1)
          : binary_node<T>(opr,branch0,branch1),
            vec1_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
            temp_         (0),
            temp_vec_node_(0)
          {
+            bool v1_is_ivec = false;
+
             if (is_vector_node(binary_node<T>::branch_[1].first))
             {
                vec1_node_ptr_ = static_cast<vector_node_ptr>(binary_node<T>::branch_[1].first);
@@ -9594,25 +9926,26 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(binary_node<T>::branch_[1].first)))
                {
                   vec1_node_ptr_ = vi->vec();
+                  v1_is_ivec     = true;
                }
             }
 
             if (vec1_node_ptr_)
             {
-               vector_holder<T>& vec0 = vec1_node_ptr_->ref();
+               if (v1_is_ivec)
+                  vds_ = vec1_node_ptr_->vds();
+               else
+                  vds_ = vds_t(vec1_node_ptr_->size());
 
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
-               temp_vec_node_ = new vector_node<T>  (temp_);
+               temp_          = new vector_holder<T>(      vds());
+               temp_vec_node_ = new vector_node<T>  (temp_,vds());
             }
          }
 
         ~vec_binop_valvec_node()
          {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
+            delete temp_;
+            delete temp_vec_node_;
          }
 
          inline T value() const
@@ -9622,16 +9955,16 @@
                const T v = binary_node<T>::branch_[0].first->value();
                            binary_node<T>::branch_[1].first->value();
 
+               T* vec0 = vds().data();
                T* vec1 = vec1_node_ptr_->ref().data();
-               T* vec2 = (*temp_).data();
 
-               loop_unroll::details lud(vec_size_);
-               const T* upper_bound = vec1 + lud.upper_bound;
+               loop_unroll::details lud(size());
+               const T* upper_bound = vec0 + lud.upper_bound;
 
-               while (vec1 < upper_bound)
+               while (vec0 < upper_bound)
                {
                   #define exprtk_loop(N)                   \
-                  vec2[N] = Operation::process(v,vec1[N]); \
+                  vec0[N] = Operation::process(v,vec1[N]); \
 
                   exprtk_loop( 0) exprtk_loop( 1)
                   exprtk_loop( 2) exprtk_loop( 3)
@@ -9644,8 +9977,8 @@
                   exprtk_loop(14) exprtk_loop(15)
                   #endif
 
+                  vec0 += lud.batch_size;
                   vec1 += lud.batch_size;
-                  vec2 += lud.batch_size;
                }
 
                int i = 0;
@@ -9653,7 +9986,7 @@
                switch (lud.remainder)
                {
                   #define case_stmt(N)                                       \
-                  case N : { vec2[i] = Operation::process(v,vec1[i]); ++i; } \
+                  case N : { vec0[i] = Operation::process(v,vec1[i]); ++i; } \
 
                   #ifndef exprtk_disable_superscalar_unroll
                   case_stmt(15) case_stmt(14)
@@ -9670,7 +10003,7 @@
                #undef exprtk_loop
                #undef case_stmt
 
-               return ((*temp_).data())[0];
+               return (vds().data())[0];
             }
             else
                return std::numeric_limits<T>::quiet_NaN();
@@ -9693,16 +10026,25 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node_ptr   vec1_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
          vector_holder_ptr temp_;
          vector_node_ptr   temp_vec_node_;
+         vds_t             vds_;
       };
 
       template <typename T, typename Operation>
@@ -9714,15 +10056,16 @@
          typedef expression_node<T>*    expression_ptr;
          typedef vector_node<T>*       vector_node_ptr;
          typedef vector_holder<T>*   vector_holder_ptr;
+         typedef vec_data_store<T>               vds_t;
 
          unary_vector_node(const operator_type& opr, expression_ptr branch0)
          : unary_node<T>(opr,branch0),
            vec0_node_ptr_(0),
-           vec_size_     (0),
-           data_         (0),
            temp_         (0),
            temp_vec_node_(0)
          {
+            bool vec0_is_ivec = false;
+
             if (is_vector_node(unary_node<T>::branch_))
             {
                vec0_node_ptr_ = static_cast<vector_node_ptr>(unary_node<T>::branch_);
@@ -9734,25 +10077,26 @@
                if (0 != (vi = dynamic_cast<vector_interface<T>*>(unary_node<T>::branch_)))
                {
                   vec0_node_ptr_ = vi->vec();
+                  vec0_is_ivec   = true;
                }
             }
 
             if (vec0_node_ptr_)
             {
-               vector_holder<T>& vec0 = vec0_node_ptr_->ref();
+               if (vec0_is_ivec)
+                  vds_ = vec0_node_ptr_->vds();
+               else
+                  vds_ = vds_t(vec0_node_ptr_->size());
 
-               vec_size_      = vec0.size();
-               data_          = new T[vec_size_];
-               temp_          = new vector_holder<T>(data_,vec_size_);
+               temp_          = new vector_holder<T>(vds());
                temp_vec_node_ = new vector_node<T>  (temp_);
             }
          }
 
         ~unary_vector_node()
          {
-            delete[] data_;
-            delete   temp_;
-            delete   temp_vec_node_;
+            delete temp_;
+            delete temp_vec_node_;
          }
 
          inline T value() const
@@ -9762,9 +10106,9 @@
             if (vec0_node_ptr_)
             {
                T* vec0 = vec0_node_ptr_->ref().data();
-               T* vec1 = (*temp_).data();
+               T* vec1 = vds().data();
 
-               loop_unroll::details lud(vec_size_);
+               loop_unroll::details lud(size());
                const T* upper_bound = vec0 + lud.upper_bound;
 
                while (vec0 < upper_bound)
@@ -9809,7 +10153,7 @@
                #undef exprtk_loop
                #undef case_stmt
 
-               return ((*temp_).data())[0];
+               return (vds().data())[0];
             }
             else
                return std::numeric_limits<T>::quiet_NaN();
@@ -9832,16 +10176,25 @@
 
          std::size_t size() const
          {
-            return vec_size_;
+            return vds().size();
+         }
+
+         vds_t& vds()
+         {
+            return vds_;
+         }
+
+         const vds_t& vds() const
+         {
+            return vds_;
          }
 
       private:
 
          vector_node_ptr   vec0_node_ptr_;
-         std::size_t       vec_size_;
-         T*                data_;
          vector_holder_ptr temp_;
          vector_node_ptr   temp_vec_node_;
+         vds_t             vds_;
       };
 
       template <typename T>
@@ -10337,7 +10690,7 @@
                      return false;
 
                   ts.size = vi->size();
-                  ts.data = vi->vec()->ref()[0];
+                  ts.data = vi->vds().data();
                   ts.type = type_store_t::e_vector;
                }
                else if (is_generally_string_node(arg_list_[i]))
@@ -11381,6 +11734,7 @@
                             for (std::size_t i = 1; i < arg_list.size(); ++i)
                             {
                                const T v = value(arg_list[i]);
+
                                if (v > result)
                                   result = v;
                             }
@@ -15349,11 +15703,31 @@
             }
          }
 
-         static control_block* create()
+         static inline control_block* create()
          {
             return new control_block;
          }
 
+         template <typename SymTab>
+         static inline void destroy(control_block*& cntrl_blck, SymTab* sym_tab)
+         {
+            if (cntrl_blck)
+            {
+               if (
+                    (0 !=   cntrl_blck->ref_count) &&
+                    (0 == --cntrl_blck->ref_count)
+                  )
+               {
+                  if (sym_tab)
+                     sym_tab->clear();
+
+                  delete cntrl_blck;
+               }
+
+               cntrl_blck = 0;
+            }
+         }
+
          std::size_t ref_count;
          st_data* data_;
       };
@@ -15368,14 +15742,7 @@
 
      ~symbol_table()
       {
-         if (control_block_)
-         {
-            if (0 == --control_block_->ref_count)
-            {
-               clear();
-               delete control_block_;
-            }
-         }
+         control_block::destroy(control_block_,this);
       }
 
       symbol_table(const symbol_table<T>& st)
@@ -15388,15 +15755,7 @@
       {
          if (this != &st)
          {
-            if (control_block_)
-            {
-               if (0 == --control_block_->ref_count)
-               {
-                  delete control_block_;
-               }
-
-               control_block_ = 0;
-            }
+            control_block::destroy(control_block_,reinterpret_cast<symbol_table<T>*>(0));
 
             control_block_ = st.control_block_;
             control_block_->ref_count++;
@@ -16364,7 +16723,10 @@
          {
             if (cntrl_blck)
             {
-               if (0 == --cntrl_blck->ref_count)
+               if (
+                    (0 !=   cntrl_blck->ref_count) &&
+                    (0 == --cntrl_blck->ref_count)
+                  )
                {
                   delete cntrl_blck;
                }
@@ -16404,7 +16766,10 @@
          {
             if (control_block_)
             {
-               if (0 == --control_block_->ref_count)
+               if (
+                    (0 !=   control_block_->ref_count) &&
+                    (0 == --control_block_->ref_count)
+                  )
                {
                   delete control_block_;
                }
@@ -19215,15 +19580,15 @@
             }
             else
             {
-               expression = new_expression;
-
                if (
                     token_is(token_t::e_ternary,prsrhlpr_t::e_hold) &&
                     (precedence == e_level00)
                   )
                {
-                  expression = parse_ternary_conditional_statement(expression);
+                  expression = parse_ternary_conditional_statement(new_expression);
                }
+               else
+                  expression = new_expression;
 
                parse_pending_string_rangesize(expression);
             }
@@ -19778,7 +20143,7 @@
          }
          else
             return expression_generator_
-                     .conditional(condition,consequent,alternative);
+                      .conditional(condition,consequent,alternative);
       }
 
       inline expression_node_ptr parse_conditional_statement_02(expression_node_ptr condition)
@@ -19914,7 +20279,7 @@
          }
          else
             return expression_generator_
-                     .conditional(condition,consequent,alternative);
+                      .conditional(condition,consequent,alternative);
       }
 
       inline expression_node_ptr parse_conditional_statement()
@@ -20063,7 +20428,7 @@
          }
          else
             return expression_generator_
-                     .conditional(condition,consequent,alternative);
+                      .conditional(condition,consequent,alternative);
       }
 
       inline expression_node_ptr parse_while_loop()
@@ -20495,11 +20860,11 @@
          else
          {
             expression_node_ptr result_node =
-                   expression_generator_.for_loop(initialiser,
-                                                  condition,
-                                                  incrementor,
-                                                  loop_body,
-                                                  brkcnt_list_.front());
+               expression_generator_.for_loop(initialiser,
+                                              condition,
+                                              incrementor,
+                                              loop_body,
+                                              brkcnt_list_.front());
             brkcnt_list_.pop_front();
 
             return result_node;
@@ -34058,6 +34423,8 @@
       {
          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
 
+         using exprtk::igeneric_function<T>::operator();
+
          print(const std::string& scalar_format = "%10.5f")
          : scalar_format_(scalar_format)
          {
@@ -34078,6 +34445,8 @@
       {
          typedef typename igeneric_function<T>::parameter_list_t parameter_list_t;
 
+         using exprtk::igeneric_function<T>::operator();
+
          println(const std::string& scalar_format = "%10.5f")
          : scalar_format_(scalar_format)
          {
diff --git a/exprtk_functional_test.txt b/exprtk_functional_test.txt
index a341e70..ee6dfe1 100644
--- a/exprtk_functional_test.txt
+++ b/exprtk_functional_test.txt
@@ -8059,4 +8059,38 @@
 equal(if(x > y){z+2;z;} else if (x > y) w; == null,true)
 equal(if(x < y){z+2;z;} else if (x < y) {w+2;w;} == z,true)
 equal(if(x > y){z+2;z;} else if (x < y) {w+2;w;} == w,true)
-equal(if(x > y){z+2;z;} else if (x > y) {w+2;w;} == null,true)
\ No newline at end of file
+equal(if(x > y){z+2;z;} else if (x > y) {w+2;w;} == null,true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; xx := yy; (xx[0] == 1) and (xx[1] == 2) and (xx[2] == 3) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; xx := (yy + 1); (xx[0] == 2) and (xx[1] == 3) and (xx[2] == 4) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; xx := (1 + yy); (xx[0] == 2) and (xx[1] == 3) and (xx[2] == 4) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; xx := 2*(yy + 1); (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 8) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; xx := (yy + 1)*2; (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 8) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := (yy + zz); (xx[0] == 2) and (xx[1] == 4) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := 2 * (yy + zz); (xx[0] == 4) and (xx[1] == 8) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := (yy + zz) * 2; (xx[0] == 4) and (xx[1] == 8) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := ((1 + yy) + (1 + zz)); (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := ((yy + 1) + (zz + 1)); (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := ((1 + yy) + (zz + 1)); (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[4] := {}; var yy[3] := {1,2,3}; var zz[2] := {1,2}; xx := ((yy + 1) + (1 + zz)); (xx[0] == 4) and (xx[1] == 6) and (xx[2] == 0) and (xx[3] == 0)},true)
+equal(~{var xx[10^5] := [-3]; xx := abs(xx);     sum(xx) == (10^5 * 3)},true)
+equal(~{var xx[10^5] := [-3]; xx := abs(xx + 1); sum(xx) == (10^5 * 2)},true)
+equal(~{var xx[10^5] := [-3]; xx := abs(1 + xx); sum(xx) == (10^5 * 2)},true)
+equal(~{var xx[10^5] := [-3]; xx := abs(xx) + 1; sum(xx) == (10^5 * 4)},true)
+equal(~{var xx[10^5] := [-3]; xx := 1 + abs(xx); sum(xx) == (10^5 * 4)},true)
+equal(~{var xx[10^5] := [-3]; xx := 2 * abs(xx + 1); sum(xx) == (10^5 * 4)},true)
+equal(~{var xx[10^5] := [-3]; xx := abs(1 + xx) * 2; sum(xx) == (10^5 * 4)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs(xx + yy); sum(xx) == (10^5 * 7)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs(xx + yy) + 1; sum(xx) == (10^5 * 8)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := 1 + abs(xx + yy); sum(xx) == (10^5 * 8)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((xx + 1) + (yy + 1)); sum(xx) == (10^5 * 5)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((1 + xx) + (1 + yy)); sum(xx) == (10^5 * 5)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((xx + 1) + (1 + yy)); sum(xx) == (10^5 * 5)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((1 + xx) + (yy + 1)); sum(xx) == (10^5 * 5)},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := 2 * abs((xx + 1) + (yy + 1)); sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := 2 * abs((1 + xx) + (1 + yy)); sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := 2 * abs((xx + 1) + (1 + yy)); sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := 2 * abs((1 + xx) + (yy + 1)); sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((xx + 1) + (yy + 1)) * 2; sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((1 + xx) + (1 + yy)) * 2; sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((xx + 1) + (1 + yy)) * 2; sum(xx) == 10^6},true)
+equal(~{var xx[10^5] := [-3]; var yy[10^5] := [-4]; xx := abs((1 + xx) + (yy + 1)) * 2; sum(xx) == 10^6},true)
\ No newline at end of file
diff --git a/exprtk_simple_example_05.cpp b/exprtk_simple_example_05.cpp
index 4adb3a0..08218a1 100644
--- a/exprtk_simple_example_05.cpp
+++ b/exprtk_simple_example_05.cpp
@@ -24,6 +24,8 @@
 template <typename T>
 struct myfunc : public exprtk::ifunction<T>
 {
+   using exprtk::ifunction<T>::operator();
+
    myfunc()
    : exprtk::ifunction<T>(2)
    {}
diff --git a/exprtk_simple_example_17.cpp b/exprtk_simple_example_17.cpp
index 997482a..f231085 100644
--- a/exprtk_simple_example_17.cpp
+++ b/exprtk_simple_example_17.cpp
@@ -27,6 +27,8 @@
 template <typename T>
 struct rnd_01 : public exprtk::ifunction<T>
 {
+   using exprtk::ifunction<T>::operator();
+
    rnd_01() : exprtk::ifunction<T>(0)
    { ::srand(static_cast<unsigned int>(time(NULL))); }