inmost_variable.h 36.5 KB
Newer Older
Kirill Terekhov's avatar
Kirill Terekhov committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24

#ifndef INMOST_AUTODIFF_ETVAR_H_INCLUDED
#define INMOST_AUTODIFF_ETVAR_H_INCLUDED
#include "inmost_common.h"
#include "inmost_expression.h"
#include "inmost_mesh.h"
#include "inmost_autodiff.h"
#include "inmost_solver.h"
#include <sstream> //for debug
#include <new>

#if defined(USE_AUTODIFF) && (!defined(USE_MESH) || !defined(USE_SOLVER))
#warning "USE_AUTODIFF require USE_MESH"
#undef USE_AUTODIFF
#endif


//TODO:
// 1. Incorporate tables
// 2. (ok, test) implement condition
// 3. (ok, test) implement stencil
// 4. (???) copying of basic_dynamic_variable
// 5. Consider optimization by checking zero variation multipliers, check that assembly do not degrade.
// 6. Document everything
25
// 7. change stencil_variable with foreach_variable and introduce function foreach(iterator beg, iterator end, arg)
Kirill Terekhov's avatar
Kirill Terekhov committed
26
// 8. enclose in namespace
Kirill Terekhov's avatar
Kirill Terekhov committed
27

Kirill Terekhov's avatar
Kirill Terekhov committed
28 29 30 31 32
//This should stop Visual Studio from complaining of very long auto-generated class types
#ifdef _MSC_VER
#pragma warning(disable : 4503)
#endif

Kirill Terekhov's avatar
Kirill Terekhov committed
33 34 35 36 37 38 39 40 41 42 43 44 45 46


#if defined(USE_AUTODIFF)
namespace INMOST
{
  
  template<class Op, class A>
  class unary_pool
  {
    A arg;
    Op operand;
  public:
    unary_pool(const A & parg) : arg(parg), operand(arg) {}
    unary_pool(const unary_pool & other) : arg(other.arg), operand(arg) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
47
    unary_pool & operator = (unary_pool const & other) {arg = other.arg; operand = Op(arg); return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
    const shell_expression<A> & get_arg() {return arg;}
    Op & get_op() {return operand;}
    const Op & get_op() const {return operand;}
  };


  template<class Op, class A>
  class unary_const_pool
  {
    A left;
    INMOST_DATA_REAL_TYPE right;
    Op operand;
  public:
    unary_const_pool(const A & pleft, INMOST_DATA_REAL_TYPE pright) : left(pleft), right(pright), operand(left,right) {}
    unary_const_pool(const unary_const_pool & other) : left(other.left), right(other.right), operand(left,right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
63
    unary_const_pool & operator = (unary_const_pool const & other) {left = other.left; right = other.right; operand = Op(left,right); return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
    const shell_expression<A> & get_arg() {return left;}
    Op & get_op() {return operand;}
    const Op & get_op() const {return operand;}
  };

  template<class Op, class A, class B>
  class binary_pool
  {
    
    A left;
    B right;
    Op operand;
  public:
    binary_pool(const A & pleft, const B & pright) : left(pleft), right(pright), operand(left,right) {}
    binary_pool(const binary_pool & other) : left(other.left), right(other.right), operand(left,right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
79
    binary_pool & operator =(binary_pool const & other) {left = other.left; right = other.right; operand = Op(left,right); return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
    const shell_expression<A> & get_left() {return left;}
    const shell_expression<B> & get_right() {return right;}
    Op & get_op() {return operand;}
    const Op & get_op() const {return operand;}
    ~binary_pool() {}
  };

  template<class Op, class A, class B, class C>
  class ternary_pool
  {
    A cond;
    B left;
    C right;
    Op operand;
  public:
    ternary_pool(const A & pcond, const B & pleft, const C & pright) : cond(pcond), left(pleft), right(pright), operand(cond,left,right) {}
    ternary_pool(const ternary_pool & other) : cond(other.cond), left(other.left), right(other.right), operand(cond,left,right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
97
    ternary_pool & operator =(ternary_pool const & other) {cond = other.cond; left = other.left; right = other.right; operand = Op(cond,left,right); return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    const shell_expression<A> & get_cond() {return cond;}
    const shell_expression<B> & get_left() {return left;}
    const shell_expression<C> & get_right() {return right;}
    Op & get_op() {return operand;}
    const Op & get_op() const {return operand;}
    ~ternary_pool() {}
  };

  template<class A, class ArgA>
  class unary_pool_expression : public shell_expression<unary_pool_expression<A,ArgA> >
  {
    unary_pool<A,ArgA> pool;
   public:
    unary_pool_expression(const unary_pool<A,ArgA> & ppool) : pool(ppool) {}
    unary_pool_expression(const unary_pool_expression & other) : pool(other.pool) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
113
    unary_pool_expression & operator = (unary_pool_expression const & other) {pool = other.pool; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
114
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
115 116
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
Kirill Terekhov's avatar
Kirill Terekhov committed
117
	__INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
Kirill Terekhov's avatar
Kirill Terekhov committed
118 119 120 121 122 123 124 125 126
  };

  template<class A, class ArgA>
  class unary_const_pool_expression : public shell_expression<unary_const_pool_expression<A,ArgA> >
  {
    unary_const_pool<A,ArgA> pool;
   public:
    unary_const_pool_expression(const unary_const_pool<A,ArgA> & ppool) : pool(ppool) {}
    unary_const_pool_expression(const unary_const_pool_expression & other) : pool(other.pool) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
127
    unary_const_pool_expression & operator = (unary_const_pool_expression const & other) {pool = other.pool; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
128
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
129 130
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
Kirill Terekhov's avatar
Kirill Terekhov committed
131
	__INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
Kirill Terekhov's avatar
Kirill Terekhov committed
132 133 134 135 136 137 138 139 140
  };

  template<class A, class ArgA, class ArgB>
  class binary_pool_expression : public shell_expression<binary_pool_expression<A,ArgA,ArgB> >
  {
    binary_pool<A,ArgA,ArgB> pool;
   public:
    binary_pool_expression(const binary_pool<A,ArgA,ArgB> & ppool) : pool(ppool) {}
    binary_pool_expression(const binary_pool_expression & other) : pool(other.pool) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
141
    binary_pool_expression & operator = (binary_pool_expression const & other) {pool = other.pool; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
142
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
143 144
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
Kirill Terekhov's avatar
Kirill Terekhov committed
145
	__INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
Kirill Terekhov's avatar
Kirill Terekhov committed
146 147 148 149 150 151 152 153 154
  };

  template<class A, class ArgA, class ArgB, class ArgC>
  class ternary_pool_expression : public shell_expression<ternary_pool_expression<A,ArgA,ArgB,ArgC> >
  {
    ternary_pool<A,ArgA,ArgB,ArgC> pool;
   public:
    ternary_pool_expression(const ternary_pool<A,ArgA,ArgB,ArgC> & ppool) : pool(ppool) {}
    ternary_pool_expression(const ternary_pool_expression & other) : pool(other.pool) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
155
    ternary_pool_expression & operator = (ternary_pool_expression const & other) {pool = other.pool; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
156
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return pool.get_op().GetValue(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
157 158
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {pool.get_op().GetJacobian(mult,r);}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {pool.get_op().GetJacobian(mult,r);}
Kirill Terekhov's avatar
Kirill Terekhov committed
159
	__INLINE void GetHessian(INMOST_DATA_REAL_TYPE multJ, Sparse::Row & J, INMOST_DATA_REAL_TYPE multH, Sparse::HessianRow & H) const {pool.get_op().GetHessian(multJ,J,multH,H);}
Kirill Terekhov's avatar
Kirill Terekhov committed
160 161 162 163 164 165 166 167 168
  };

  class abstract_dynamic_variable
  {
  public:
    virtual INMOST_DATA_REAL_TYPE Value (const Storage & e) const = 0;
    virtual multivar_expression Variable(const Storage & e) const = 0;
    virtual void GetVariation(const Storage & e, Sparse::Row & r) const = 0;
    virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
169
    virtual abstract_dynamic_variable * Copy() const = 0;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
170
    virtual ~abstract_dynamic_variable() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
  };

  template<typename RetType>
  class get_variable
  {
  public:
    virtual RetType operator()(const Storage & e) const = 0;
  };

  template<>
  class get_variable<multivar_expression>
  {
    const abstract_dynamic_variable & var;
  public:
    typedef multivar_expression type;
    get_variable(const abstract_dynamic_variable & var) : var(var) {}
    multivar_expression operator()(const Storage & e) const {return var.Variable(e);}
  };

  template<>
  class get_variable<INMOST_DATA_REAL_TYPE>
  {
    const abstract_dynamic_variable & var;
  public:
    typedef INMOST_DATA_REAL_TYPE type;
    get_variable(const abstract_dynamic_variable & var) : var(var) {}
    INMOST_DATA_REAL_TYPE operator()(const Storage & e) const {return var.Value(e);}
  };

Kirill Terekhov's avatar
Kirill Terekhov committed
200
  
Kirill Terekhov's avatar
Kirill Terekhov committed
201 202 203 204 205 206 207 208 209 210 211 212 213



  template<class VariableType>
  class basic_dynamic_variable : public abstract_dynamic_variable
  {
  public:
    typedef VariableType Var;
    virtual INMOST_DATA_REAL_TYPE Value(const Storage & e) const = 0;
    virtual multivar_expression Variable(const Storage & e) const = 0;
    virtual VariableType operator[](const Storage & e) const = 0;
    virtual void GetVariation(const Storage & e, Sparse::Row & r) const = 0;
    virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
214
    virtual abstract_dynamic_variable * Copy() const = 0;
Kirill Terekhov's avatar
Fixes  
Kirill Terekhov committed
215
    virtual ~basic_dynamic_variable() {}
Kirill Terekhov's avatar
Kirill Terekhov committed
216 217 218 219 220 221 222 223 224 225 226 227
  };

  template<class VariableType, class Derived>
  class shell_dynamic_variable : virtual public basic_dynamic_variable<VariableType>
  {
  public:
    typedef VariableType Var;
    virtual INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return static_cast<const Derived *>(this)->Value(e);}
    virtual multivar_expression operator ()(const Storage & e) const {return static_cast<const Derived *>(this)->Variable(e);}
    virtual VariableType operator[](const Storage & e) const {return (*static_cast<const Derived *>(this))[e];}
    virtual void GetVariation(const Storage & e, Sparse::Row & r) const {static_cast<const Derived *>(this)->GetVariation(e,r);}
    virtual void GetVariation(const Storage & e, Sparse::RowMerger & r) const {static_cast<const Derived *>(this)->GetVariation(e,r);}
Kirill Terekhov's avatar
Kirill Terekhov committed
228 229 230
    operator Derived & () {return *static_cast<Derived *>(this);}
    operator const Derived & () const {return *static_cast<const Derived *>(this);}
    virtual abstract_dynamic_variable * Copy() const { return static_cast<const Derived *>(this)->Copy(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
231
  };
Kirill Terekhov's avatar
Kirill Terekhov committed
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253

  class stored_variable_expression : public shell_dynamic_variable<multivar_expression,stored_variable_expression>
  {
    abstract_dynamic_variable * var;
  public:
    stored_variable_expression() : var(NULL) {}
    stored_variable_expression(const abstract_dynamic_variable & pvar) : var(pvar.Copy()) {}
    stored_variable_expression(const stored_variable_expression & other) : var(other.var->Copy()) {}
    ~stored_variable_expression() {delete var; var = NULL;}
    stored_variable_expression operator =(stored_variable_expression const & other) {var = other.var->Copy(); return *this;}
    stored_variable_expression operator =(const abstract_dynamic_variable & pvar) {var = pvar.Copy(); return *this;}
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return var->Value(e);}
    multivar_expression Variable(const Storage & e) const {return var->Variable(e);}
    multivar_expression operator [](const Storage & e) const {return var->Variable(e);}
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }

    template<typename T>
    get_variable<T> get_variable() {return get_variable<T>(*var);}
    abstract_dynamic_variable & retrive_expression() {return *var;}
    const abstract_dynamic_variable & retrive_expression() const {return *var;}
  };
Kirill Terekhov's avatar
Kirill Terekhov committed
254
	
Kirill Terekhov's avatar
Kirill Terekhov committed
255 256
  
  class dynamic_variable : public shell_dynamic_variable<var_expression,dynamic_variable >
Kirill Terekhov's avatar
Kirill Terekhov committed
257 258 259 260 261 262 263 264 265 266 267 268
  {
  private:
    Automatizator & aut;
    Tag index_tag, value_tag;
    MarkerType mask;
    INMOST_DATA_ENUM_TYPE comp;
  public:
    dynamic_variable(Automatizator & paut, INMOST_DATA_ENUM_TYPE pregval, INMOST_DATA_ENUM_TYPE pcomp = 0) : aut(paut), comp(pcomp) 
    {
      if( pregval != ENUMUNDEF )
      {
        mask = aut.GetDynamicMask(pregval);
269 270
        value_tag = aut.GetDynamicValueTag(pregval);
        index_tag = aut.GetDynamicIndexTag(pregval);
Kirill Terekhov's avatar
Kirill Terekhov committed
271 272 273 274 275 276 277 278 279 280
      }
    }
    dynamic_variable(const dynamic_variable & other) : aut(other.aut), index_tag(other.index_tag), value_tag(other.value_tag), mask(other.mask), comp(other.comp) {}
    dynamic_variable & operator =(const dynamic_variable & other) 
    {
      aut = other.aut; 
      index_tag = other.index_tag; 
      value_tag = other.value_tag;
      mask = other.mask;
      comp = other.comp;
Kirill Terekhov's avatar
Kirill Terekhov committed
281
      return * this;
Kirill Terekhov's avatar
Kirill Terekhov committed
282
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
283 284
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return e->RealArray(value_tag)[comp];}
    INMOST_DATA_ENUM_TYPE Index(const Storage & e) const {return (!mask || e->GetMarker(mask))?e->IntegerArray(index_tag)[comp]:ENUMUNDEF;}
Kirill Terekhov's avatar
Kirill Terekhov committed
285 286 287
    multivar_expression Variable(const Storage & e) const 
    {
      if( !mask || e->GetMarker(mask) )
Kirill Terekhov's avatar
Kirill Terekhov committed
288
        return multivar_expression(e->RealArray(value_tag)[comp],e->IntegerArray(index_tag)[comp]);
Kirill Terekhov's avatar
Kirill Terekhov committed
289 290 291 292 293 294
      else
        return multivar_expression(e->Real(value_tag));
    }
    var_expression operator [](const Storage & e) const {return var_expression(e->Real(value_tag),(!mask || e->GetMarker(mask))?e->Integer(index_tag):ENUMUNDEF);}
    Tag IndexTag() {return index_tag;}
    Tag ValueTag() {return value_tag;}
Kirill Terekhov's avatar
Kirill Terekhov committed
295 296
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
297
    bool isUnknown(const Storage & e) const {return (!mask || e->GetMarker(mask))?true:false;}
Kirill Terekhov's avatar
Kirill Terekhov committed
298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new dynamic_variable(*this));}
  };

  
  class static_variable : public shell_dynamic_variable<const_expression,static_variable>
  {
  private:
    Tag value_tag;
    INMOST_DATA_ENUM_TYPE comp;
  public:
    static_variable(Tag t, INMOST_DATA_ENUM_TYPE pcomp = 0) : value_tag(t), comp(pcomp)  {}
    static_variable(const static_variable & other) : value_tag(other.value_tag), comp(other.comp) {}
    static_variable & operator =(const static_variable & other) 
    {
      value_tag = other.value_tag;
      comp = other.comp;
      return * this;
    }
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return e->RealArray(value_tag)[comp];}
    multivar_expression Variable(const Storage & e) const 
    {
      return multivar_expression(e->RealArray(value_tag)[comp]);
    }
    const_expression operator [](const Storage & e) const {return const_expression(e->RealArray(value_tag)[comp]);}
    Tag ValueTag() {return value_tag;}
Kirill Terekhov's avatar
Kirill Terekhov committed
323 324
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
325 326 327 328 329 330 331 332 333 334
    bool isUnknown(const Storage & e) const {return false;}
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new static_variable(*this));}
  };

  class stored_variable : public shell_dynamic_variable<multivar_expression,stored_variable>
  {
  private:
    Tag variable_tag;
    INMOST_DATA_ENUM_TYPE comp;
  public:
335 336 337 338
    stored_variable(Tag t, INMOST_DATA_ENUM_TYPE pcomp = 0) : variable_tag(t), comp(pcomp)  
	{
		assert(t.GetDataType() == DATA_REAL || t.GetDataType() == DATA_VARIABLE);
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
339 340 341 342 343 344 345
    stored_variable(const stored_variable & other) : variable_tag(other.variable_tag), comp(other.comp) {}
    stored_variable & operator =(const stored_variable & other) 
    {
      variable_tag = other.variable_tag;
      comp = other.comp;
      return * this;
    }
346 347 348 349 350 351 352
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const 
	{
		if( variable_tag.GetDataType() == DATA_VARIABLE )
			return e->VariableArray(variable_tag)[comp].GetValue();
		else if( variable_tag.GetDataType() == DATA_REAL )
			return e->RealArray(variable_tag)[comp];
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
353 354
    multivar_expression Variable(const Storage & e) const 
    {
355 356 357 358
		if( variable_tag.GetDataType() == DATA_VARIABLE )
			return e->VariableArray(variable_tag)[comp];
		else if( variable_tag.GetDataType() == DATA_REAL )
			return variable(e->RealArray(variable_tag)[comp]);
Kirill Terekhov's avatar
Kirill Terekhov committed
359
    }
360 361 362 363 364 365 366
    multivar_expression operator [](const Storage & e) const 
	{
		if( variable_tag.GetDataType() == DATA_VARIABLE )
			return e->VariableArray(variable_tag)[comp];
		else if( variable_tag.GetDataType() == DATA_REAL )
			return variable(e->RealArray(variable_tag)[comp]);
	}
Kirill Terekhov's avatar
Kirill Terekhov committed
367
    Tag VariableTag() {return variable_tag;}
Kirill Terekhov's avatar
Kirill Terekhov committed
368 369
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
370 371
    bool isUnknown(const Storage & e) const {return false;}
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new stored_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
372 373 374 375 376 377
  };

  template<class A>
  class stencil_variable : public shell_dynamic_variable< stencil_expression<typename A::Var>, stencil_variable<A> >
  {
  private:
Kirill Terekhov's avatar
Kirill Terekhov committed
378 379
    Tag tag_elems;
	Tag tag_coefs;
Kirill Terekhov's avatar
Kirill Terekhov committed
380 381
    const A & Arg;
  public:
Kirill Terekhov's avatar
Kirill Terekhov committed
382 383 384
    stencil_variable(Tag tag_elems, Tag tag_coefs, const shell_dynamic_variable<typename A::Var,A> & parg) : tag_elems(tag_elems), tag_coefs(tag_coefs), Arg(parg) {}
    stencil_variable(const stencil_variable & other) : tag_elems(other.tag_elems), tag_coefs(other.tag_coefs), Arg(other.Arg) {}
    stencil_variable & operator =(const stencil_variable & other) {tag_elems = other.tag_elems; tag_coefs = other.tag_coefs; Arg = other.Arg; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
385 386 387 388 389 390 391 392
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    stencil_expression<typename A::Var> operator [](const Storage & e) const
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
393 394 395 396 397 398 399
      dynarray< const_multiplication_expression<typename A::Var>, 64> tmp;
	  Storage::real_array      coefs = e.RealArray(tag_coefs);
	  Storage::reference_array elems = e.RealArray(tag_elems);
	  assert(coefs.size() == elems.size());
      tmp.resize(elems.size());
      for(INMOST_DATA_ENUM_TYPE k = 0; k < elems.size(); ++k)
		  tmp[k] = const_multiplication_expression<A>(Arg[elems[k]],coefs[k]);
Kirill Terekhov's avatar
Kirill Terekhov committed
400 401
      return stencil_expression<typename A::Var>(tmp);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
402 403
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
404 405 406 407 408 409 410 411 412 413
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new stencil_variable(*this));}
  };

  template<class A>
  class table_variable : public shell_dynamic_variable< unary_pool_expression< function_expression<typename A::Var>,typename A::Var > , table_variable<A> >
  {
    const A & Arg;
    const keyval_table & Table;
  public:
    table_variable(const shell_dynamic_variable<typename A::Var,A> & parg, const keyval_table & ptable) : Arg(parg), Table(ptable) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
414
    table_variable(const table_variable & other) : Arg(other.Arg), Table(other.Table) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429
    table_variable & operator = (table_variable const & other) {Arg = other.Arg; Table = other.Table; return * this;}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    unary_pool_expression< function_expression<typename A::Var> ,typename A::Var > operator [](const Storage & e) const
    {
      typename A::Var arg = Arg[e];
      unary_pool< function_expression<typename A::Var>, typename A::Var> pool(arg);
      std::pair<INMOST_DATA_REAL_TYPE, INMOST_DATA_REAL_TYPE> both = Table.GetBoth(arg.GetValue());
      pool.get_op().SetFunctionValue(both.first);
      pool.get_op().SetFunctionDerivative(both.second);
      return unary_pool_expression< function_expression<typename A::Var>, typename A::Var >(pool);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
430 431
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
432
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new table_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
433 434 435 436 437 438 439 440
  };

  template<class Expr, class A>
  class unary_custom_variable : public shell_dynamic_variable< unary_pool_expression<Expr, typename A::Var >,unary_custom_variable<Expr,A> >
  {
  private:
    const A & Arg;
  public:
Kirill Terekhov's avatar
Kirill Terekhov committed
441
    unary_custom_variable(const shell_dynamic_variable<typename A::Var,A> & parg) : Arg(parg) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
442
    unary_custom_variable(const unary_custom_variable & other) : Arg(other.Arg) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
443
    unary_custom_variable & operator =(unary_custom_variable const & other) {Arg = other.Arg; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
444 445 446 447 448 449 450 451
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    unary_pool_expression<Expr, typename A::Var > operator [](const Storage & e) const 
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
452
      unary_pool<Expr,typename A::Var> pool(Arg[e]);
Kirill Terekhov's avatar
Kirill Terekhov committed
453 454
      return unary_pool_expression<Expr, typename A::Var >(pool);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
455 456
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
457
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new unary_custom_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
458 459 460 461 462 463 464 465 466 467 468 469 470
  };


  template<class Expr, class A, class B>
  class binary_custom_variable : public shell_dynamic_variable< binary_pool_expression<Expr, typename A::Var, typename B::Var >,binary_custom_variable<Expr,A,B> >
  {
  private:
    const A & Left;
    const B & Right;
  public:
    binary_custom_variable(const shell_dynamic_variable<typename A::Var,A> & pleft, const shell_dynamic_variable<typename B::Var,B> & pright) 
    : Left(pleft), Right(pright) {}
    binary_custom_variable(const binary_custom_variable & other) : Left(other.Left), Right(other.Right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
471
    binary_custom_variable & operator =(binary_custom_variable const & other) {Left = other.Left; Right = other.Right; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
472 473 474 475 476 477 478 479
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    binary_pool_expression<Expr, typename A::Var, typename B::Var > operator [](const Storage & e) const 
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
480
      binary_pool<Expr,typename A::Var,typename B::Var> pool(Left[e],Right[e]);
Kirill Terekhov's avatar
Kirill Terekhov committed
481 482
      return binary_pool_expression<Expr, typename A::Var, typename B::Var >(pool);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
483 484
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
485
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new binary_custom_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
486 487 488 489 490 491 492 493 494 495 496 497
  };

  template<class Expr, class A>
  class unary_const_custom_variable : public shell_dynamic_variable< unary_const_pool_expression<Expr, typename A::Var >,unary_const_custom_variable<Expr,A> >
  {
  private:
    const A & Left;
    INMOST_DATA_REAL_TYPE Right;
  public:
    unary_const_custom_variable(const shell_dynamic_variable<typename A::Var,A> & pleft, INMOST_DATA_REAL_TYPE pright) 
    : Left(pleft), Right(pright) {}
    unary_const_custom_variable(const unary_const_custom_variable & other) : Left(other.Left), Right(other.Right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
498
    unary_const_custom_variable & operator =(unary_const_custom_variable const & other) {Left = other.Left; Right = other.Right; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
499 500 501 502 503 504 505 506
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    unary_const_pool_expression<Expr, typename A::Var > operator [](const Storage & e) const 
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
507
      unary_const_pool<Expr,typename A::Var> pool(Left[e],Right);
Kirill Terekhov's avatar
Kirill Terekhov committed
508 509
      return unary_const_pool_expression<Expr, typename A::Var >(pool);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
510 511
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
512
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new unary_const_custom_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
513 514 515 516 517 518 519 520 521 522 523 524 525
  };

  template<class Expr, class A, class B, class C>
  class ternary_custom_variable : public shell_dynamic_variable< ternary_pool_expression<Expr, typename A::Var, typename B::Var, typename C::Var >,ternary_custom_variable<Expr,A,B,C> >
  {
  private:
    const A & Cond;
    const B & Left;
    const C & Right;
  public:
    ternary_custom_variable(const shell_dynamic_variable<typename A::Var,A> & pcond, const shell_dynamic_variable<typename B::Var,B> & pleft, const shell_dynamic_variable<typename C::Var,C> & pright) 
    : Cond(pcond), Left(pleft), Right(pright) {}
    ternary_custom_variable(const ternary_custom_variable & other) : Left(other.Left), Right(other.Right) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
526
    ternary_custom_variable & operator =(ternary_custom_variable const & other) {Left = other.Left; Right = other.Right; return * this;}
Kirill Terekhov's avatar
Kirill Terekhov committed
527 528 529 530 531 532 533 534
    INMOST_DATA_REAL_TYPE Value(const Storage & e) const {return (*this)[e].GetValue();}
    multivar_expression Variable(const Storage & e) const
    {
      multivar_expression ret = (*this)[e];
      return ret;
    }
    ternary_pool_expression<Expr, typename A::Var, typename B::Var, typename C::Var > operator [](const Storage & e) const 
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
535
      ternary_pool<Expr,typename A::Var,typename B::Var, typename C::Var> pool(Cond[e],Left[e],Right[e]);
Kirill Terekhov's avatar
Kirill Terekhov committed
536 537
      return ternary_pool_expression<Expr, typename A::Var, typename B::Var, typename C::Var>(pool);
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
538 539
    void GetVariation(const Storage & e, Sparse::Row & r) const { (*this)[e].GetJacobian(1.0,r); }
    void GetVariation(const Storage & e, Sparse::RowMerger & r) const { (*this)[e].GetJacobian(1.0,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
540
    abstract_dynamic_variable * Copy() const {return static_cast<abstract_dynamic_variable *>(new ternary_custom_variable(*this));}
Kirill Terekhov's avatar
Kirill Terekhov committed
541 542
  };
  typedef abstract_dynamic_variable abstract_variable;
543 544
}

Kirill Terekhov's avatar
Kirill Terekhov committed
545 546 547
template<class A, class B, class C> 
                           __INLINE 
							  INMOST::ternary_custom_variable<INMOST::condition_expression<typename A::Var, typename B::Var, typename C::Var>,A,B,C> condition(INMOST::shell_dynamic_variable<typename A::Var, A> const & control, INMOST::shell_dynamic_variable<typename B::Var, B> const & if_ge_zero, INMOST::shell_dynamic_variable<typename C::Var, C> const & if_lt_zero) { return INMOST::ternary_custom_variable<INMOST::condition_expression<typename A::Var, typename B::Var, typename C::Var>,A,B,C>(control,if_ge_zero,if_lt_zero); }
548
template<class A>          __INLINE                                 INMOST::unary_custom_variable<INMOST::unary_minus_expression<typename A::Var>,A> operator-(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::unary_minus_expression<typename A::Var>,A>(Arg); }
Kirill Terekhov's avatar
Kirill Terekhov committed
549
template<class A>          __INLINE                                  INMOST::unary_custom_variable<INMOST::unary_plus_expression<typename A::Var>,A> operator+(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::unary_plus_expression<typename A::Var>,A>(Arg); }
550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
template<class A>          __INLINE                                         INMOST::unary_custom_variable<INMOST::abs_expression<typename A::Var>,A>      fabs(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::abs_expression<typename A::Var>,A>(Arg); }
template<class A>          __INLINE                                         INMOST::unary_custom_variable<INMOST::exp_expression<typename A::Var>,A>       exp(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::exp_expression<typename A::Var>,A>(Arg); }
template<class A>          __INLINE                                         INMOST::unary_custom_variable<INMOST::log_expression<typename A::Var>,A>       log(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::log_expression<typename A::Var>,A>(Arg); }
template<class A>          __INLINE                                         INMOST::unary_custom_variable<INMOST::sin_expression<typename A::Var>,A>       sin(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::sin_expression<typename A::Var>,A>(Arg ); }
template<class A>          __INLINE                                         INMOST::unary_custom_variable<INMOST::cos_expression<typename A::Var>,A>       cos(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::cos_expression<typename A::Var>,A>(Arg); }
template<class A>          __INLINE                                        INMOST::unary_custom_variable<INMOST::sqrt_expression<typename A::Var>,A>      sqrt(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg) { return INMOST::unary_custom_variable<INMOST::sqrt_expression<typename A::Var>,A>(Arg); }
template<class A>          __INLINE              INMOST::unary_const_custom_variable<INMOST::variation_multiplication_expression<typename A::Var>,A> variation(INMOST::shell_dynamic_variable<typename A::Var, A> const & Arg, INMOST_DATA_REAL_TYPE Mult) {return INMOST::unary_const_custom_variable<INMOST::variation_multiplication_expression<typename A::Var>,A>(Arg,Mult);}
template<class A, class B> __INLINE                INMOST::binary_custom_variable<INMOST::addition_expression<typename A::Var,typename B::Var>,A, B> operator+(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::binary_custom_variable<INMOST::addition_expression<typename A::Var,typename B::Var>,A, B> (Left, Right); }
template<class A, class B> __INLINE             INMOST::binary_custom_variable<INMOST::subtraction_expression<typename A::Var,typename B::Var>,A, B> operator-(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::binary_custom_variable<INMOST::subtraction_expression<typename A::Var,typename B::Var>, A, B> (Left, Right); }
template<class A, class B> __INLINE          INMOST::binary_custom_variable<INMOST::multiplication_expression<typename A::Var,typename B::Var>,A, B> operator*(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::binary_custom_variable<INMOST::multiplication_expression<typename A::Var,typename B::Var>, A, B> (Left, Right); }
template<class A, class B> __INLINE                INMOST::binary_custom_variable<INMOST::division_expression<typename A::Var,typename B::Var>,A, B> operator/(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::binary_custom_variable<INMOST::division_expression<typename A::Var,typename B::Var>, A, B> (Left, Right); }
template<class A, class B> __INLINE                     INMOST::binary_custom_variable<INMOST::pow_expression<typename A::Var,typename B::Var>,A, B>       pow(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::binary_custom_variable<INMOST::pow_expression<typename A::Var,typename B::Var>,A, B>(Left, Right); }
template<class B>          __INLINE                             INMOST::unary_const_custom_variable<INMOST::const_pow_expression<typename B::Var>,B>       pow(INMOST_DATA_REAL_TYPE Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::unary_const_custom_variable<INMOST::const_pow_expression<typename B::Var>,B>(Left, Right); }
template<class A>          __INLINE                             INMOST::unary_const_custom_variable<INMOST::pow_const_expression<typename A::Var>,A>       pow(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST_DATA_REAL_TYPE Right) { return INMOST::unary_const_custom_variable<INMOST::pow_const_expression<typename A::Var>,A>(Left, Right); }
template<class B>          __INLINE                  INMOST::unary_const_custom_variable<INMOST::const_multiplication_expression<typename B::Var>,B> operator*(INMOST_DATA_REAL_TYPE Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::unary_const_custom_variable<INMOST::const_multiplication_expression<typename B::Var>,B>(Right,Left); }
template<class A>          __INLINE                  INMOST::unary_const_custom_variable<INMOST::const_multiplication_expression<typename A::Var>,A> operator*(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST_DATA_REAL_TYPE Right) { return INMOST::unary_const_custom_variable<INMOST::const_multiplication_expression<typename A::Var>,A>(Left,Right); }
template<class B>          __INLINE                            INMOST::unary_const_custom_variable<INMOST::reciprocal_expression<typename B::Var>,B> operator/(INMOST_DATA_REAL_TYPE Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::unary_const_custom_variable<INMOST::reciprocal_expression<typename B::Var>,B>(Right,Left); }
template<class A>          __INLINE                        INMOST::unary_const_custom_variable<INMOST::const_division_expression<typename A::Var>,A> operator/(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST_DATA_REAL_TYPE Right) { return INMOST::unary_const_custom_variable<INMOST::const_division_expression<typename A::Var>,A>(Left, Right); }
template<class B>          __INLINE                        INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename B::Var>,B> operator+(INMOST_DATA_REAL_TYPE Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename B::Var>,B>(Right,Left); }
template<class A>          __INLINE                        INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename A::Var>,A> operator+(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST_DATA_REAL_TYPE Right) { return INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename A::Var>,A>(Left,Right); }
template<class B>          __INLINE                     INMOST::unary_const_custom_variable<INMOST::const_subtraction_expression<typename B::Var>,B> operator-(INMOST_DATA_REAL_TYPE Left, INMOST::shell_dynamic_variable<typename B::Var,B> const & Right) { return INMOST::unary_const_custom_variable<INMOST::const_subtraction_expression<typename B::Var>,B>(Right, Left); }
template<class A>          __INLINE                        INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename A::Var>,A> operator-(INMOST::shell_dynamic_variable<typename A::Var,A> const & Left, INMOST_DATA_REAL_TYPE Right) { return INMOST::unary_const_custom_variable<INMOST::const_addition_expression<typename A::Var>,A>(Left, -Right); }
Kirill Terekhov's avatar
Kirill Terekhov committed
572
template<class A>          __INLINE                                                                                      INMOST::stencil_variable<A>   stencil(INMOST::Tag tag_elems, INMOST::Tag tag_coefs, INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg) { return INMOST::stencil_variable<A>(tag_elems,tag_coefs,Arg); }
Kirill Terekhov's avatar
Kirill Terekhov committed
573
template<class A>          __INLINE                                                                                        INMOST::table_variable<A> get_table(INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg, const INMOST::keyval_table & Table) {return INMOST::table_variable<A>(Arg,Table);}
Kirill Terekhov's avatar
Kirill Terekhov committed
574 575 576 577 578 579 580 581
template<class A>          __INLINE                                                                                    INMOST::stencil_expression<A>   stencil(INMOST::HandleType * elems, INMOST_DATA_REAL_TYPE * coefs, INMOST_DATA_ENUM_TYPE num, INMOST::shell_dynamic_variable<typename A::Var,A> const & Arg)
{
	INMOST::dynarray< INMOST::const_multiplication_expression<typename A::Var>, 64> tmp;
	for( INMOST_DATA_ENUM_TYPE k = 0; k < num; ++k) if( elems[k] != 0 )
		tmp.push_back(INMOST::const_multiplication_expression<typename A::Var>(Arg[elems[k]],coefs[k]));
	return INMOST::stencil_expression<typename A::Var>(tmp);
}

582 583 584

  

Kirill Terekhov's avatar
Kirill Terekhov committed
585 586 587

#endif
#endif