inmost_expression.h 60 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
25
26
27
28
29
30
#ifndef INMOST_AUTODIFF_ETEXPR_H_INCLUDED
#define INMOST_AUTODIFF_ETEXPR_H_INCLUDED
#include "inmost_common.h"
#include "inmost_sparse.h"
#include <sstream> //for debug
#include <new>

#if defined(USE_AUTODIFF) && !defined(USE_SOLVER)
#warning "USE_AUTODIFF require USE_SOLVER"
#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. floor, ceil, atan, acos, asin, max, min functions
// 7. choice of directional derivatives at discontinuities for abs, pow, max, min (see ADOL-C)


#if defined(USE_AUTODIFF)
namespace INMOST
{

	class basic_expression
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
31
    basic_expression() {}//if( GetAutodiffPrint() ) std::cout << this << " Created" << std::endl;}
Kirill Terekhov's avatar
Kirill Terekhov committed
32
    basic_expression(const basic_expression & other) {};//std::cout << this << " Created from " << &other << std::endl;}
33
		virtual INMOST_DATA_REAL_TYPE GetValue() const = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
34
35
36
37
		virtual void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const = 0;
    virtual void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const = 0;
    //virtual void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const = 0;
    //virtual void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const = 0;
Kirill Terekhov's avatar
Kirill Terekhov committed
38
    virtual ~basic_expression() {}//if( GetAutodiffPrint() ) std::cout << this << " Destroied" << std::endl;}
Kirill Terekhov's avatar
Kirill Terekhov committed
39
40
	};

Kirill Terekhov's avatar
Kirill Terekhov committed
41
42
43
  bool CheckCurrentAutomatizator();
  void FromBasicExpression(Sparse::Row & entries, const basic_expression & expr);
  void AddBasicExpression(Sparse::Row & entries, INMOST_DATA_REAL_TYPE multme, INMOST_DATA_REAL_TYPE multit, const basic_expression & expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
44
  void FromGetJacobian(const basic_expression & expr, INMOST_DATA_REAL_TYPE mult, Sparse::Row & r);
Kirill Terekhov's avatar
Kirill Terekhov committed
45
46
47
  //bool GetAutodiffPrint();
  //void SetAutodiffPrint(bool set);

Kirill Terekhov's avatar
Kirill Terekhov committed
48
49
50
51
	template<class Derived>
	class shell_expression : virtual public basic_expression
	{
	public:
Kirill Terekhov's avatar
Kirill Terekhov committed
52
    shell_expression() {}// if( GetAutodiffPrint() ) std::cout << this << " Shell Created for " << dynamic_cast<basic_expression *>(this) << std::endl;}
Kirill Terekhov's avatar
Kirill Terekhov committed
53
54
		shell_expression(const shell_expression & other) {}//std::cout << this << " Shell Created from " << &other << std::endl;}
		__INLINE virtual INMOST_DATA_REAL_TYPE GetValue() const {return static_cast<const Derived *>(this)->GetValue(); }
Kirill Terekhov's avatar
Kirill Terekhov committed
55
56
57
58
    __INLINE virtual void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const { return static_cast<const Derived *>(this)->GetJacobian(mult,r); }
    __INLINE virtual void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const { return static_cast<const Derived *>(this)->GetJacobian(mult,r); }
    //__INLINE virtual void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {return static_cast<const Derived *>(this)->GetHessian(mult,r); }
    //__INLINE virtual void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {return static_cast<const Derived *>(this)->GetHessian(mult,r); }
Kirill Terekhov's avatar
Kirill Terekhov committed
59
60
    operator Derived & () {return *static_cast<Derived *>(this);}
    operator const Derived & () const {return *static_cast<const Derived *>(this);}
Kirill Terekhov's avatar
Kirill Terekhov committed
61
    ~shell_expression() {}// if( GetAutodiffPrint() ) std::cout << this << " Shell Destroied for " << dynamic_cast<basic_expression *>(this) << std::endl;}
Kirill Terekhov's avatar
Kirill Terekhov committed
62
63
64
65
66
    //Derived * GetDerived() { return dynamic_cast<Derived *>(this); }
	};

  
 
Kirill Terekhov's avatar
Kirill Terekhov committed
67
68
69
70
71
72
73
  class const_expression : public shell_expression<const_expression>
  {
    INMOST_DATA_REAL_TYPE value;
  public:
    const_expression(const const_expression & other) :value(other.value) {}
    const_expression(INMOST_DATA_REAL_TYPE pvalue) : value(pvalue) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
74
75
76
77
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {}
    //__INLINE void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {}
    //__INLINE void GetHessian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {}
Kirill Terekhov's avatar
Kirill Terekhov committed
78
79
80
81
82
83
    __INLINE const_expression & operator =(const_expression const & other)
    {
      value = other.value;
      return *this;
    }
  };
Kirill Terekhov's avatar
Kirill Terekhov committed
84
85
86
87
88
89
90
91
92
93
  

  class var_expression : public shell_expression<var_expression>
  {
    INMOST_DATA_REAL_TYPE value;
    INMOST_DATA_ENUM_TYPE index;
  public:
    var_expression(const var_expression & other) :value(other.value), index(other.index) {}
    var_expression(INMOST_DATA_REAL_TYPE pvalue, INMOST_DATA_ENUM_TYPE pindex) : value(pvalue), index(pindex) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
94
95
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const {if( index != ENUMUNDEF ) r[index] += mult;}
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const {if( index != ENUMUNDEF ) r[index] += mult;}
Kirill Terekhov's avatar
Kirill Terekhov committed
96
97
98
99
100
101
102
103
104
105
106
107
    __INLINE var_expression & operator =(var_expression const & other)
    {
      value = other.value;
      index = other.index;
      return *this;
    }
    bool check_nans() const
    {
      return value != value;
    }
  };

Kirill Terekhov's avatar
Kirill Terekhov committed
108

Kirill Terekhov's avatar
Kirill Terekhov committed
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
  class multivar_expression : public shell_expression<multivar_expression>
  {
    INMOST_DATA_REAL_TYPE value;
    Sparse::Row entries;
  public:
    multivar_expression() :value(0) {}
    multivar_expression(INMOST_DATA_REAL_TYPE pvalue) : value(pvalue) {}
    multivar_expression(const multivar_expression & other) : value(other.value), entries(other.entries) {}
    multivar_expression(INMOST_DATA_REAL_TYPE pvalue, Sparse::Row & pentries)
     : value(pvalue), entries(pentries) {}
    multivar_expression(INMOST_DATA_REAL_TYPE pvalue, INMOST_DATA_ENUM_TYPE pindex, INMOST_DATA_REAL_TYPE pdmult = 1.0)
     : value(pvalue)
    {
      entries.Push(pindex,pdmult);
    }
    multivar_expression(const basic_expression & expr)
    {
      value = expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
127
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
128
        FromBasicExpression(entries,expr); //Optimized version
Kirill Terekhov's avatar
Kirill Terekhov committed
129
      else expr.GetJacobian(1.0,entries);
Kirill Terekhov's avatar
Kirill Terekhov committed
130
131
132
    }
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
    __INLINE void SetValue(INMOST_DATA_REAL_TYPE val) { value = val; }
Kirill Terekhov's avatar
Kirill Terekhov committed
133
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
134
135
136
137
    {
      for(Sparse::Row::const_iterator it = entries.Begin(); it != entries.End(); ++it)
        r[it->first] += it->second*mult;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
138
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
139
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
140
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
141
        FromGetJacobian(*this,mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
142
143
144
145
146
      else
      {
        for(Sparse::Row::const_iterator it = entries.Begin(); it != entries.End(); ++it)
          r[it->first] += it->second*mult;
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
147
148
149
150
151
152
153
154
155
156
    }
    __INLINE multivar_expression & operator = (INMOST_DATA_REAL_TYPE pvalue)
    {
      value = pvalue;
      entries.Clear();
      return *this;
    }
    __INLINE multivar_expression & operator = (basic_expression const & expr)
    {
      value = expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
157
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
158
        FromBasicExpression(entries,expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
159
160
161
      else
      {
        Sparse::Row tmp;
Kirill Terekhov's avatar
Kirill Terekhov committed
162
        expr.GetJacobian(1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
163
164
        entries.Swap(tmp);
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
165
166
167
168
169
170
171
172
173
174
175
176
177
      return *this;
    }
    __INLINE multivar_expression & operator = (multivar_expression const & other)
    {
      value = other.value;
      entries = other.entries;
      return *this;
    }
    __INLINE Sparse::Row & GetRow() {return entries;}
    __INLINE const Sparse::Row & GetRow() const {return entries;}
    __INLINE multivar_expression & operator +=(basic_expression const & expr)
    {
      value += expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
178
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
179
        AddBasicExpression(entries,1.0,1.0,expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
180
181
182
      else
      { 
        Sparse::Row tmp(entries);
Kirill Terekhov's avatar
Kirill Terekhov committed
183
        expr.GetJacobian(1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
184
185
        entries.Swap(tmp);
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
186
187
188
189
190
      return *this;
    }
    __INLINE multivar_expression & operator -=(basic_expression const & expr)
    {
      value -= expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
191
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
192
        AddBasicExpression(entries,1.0,-1.0,expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
193
194
195
      else
      {
        Sparse::Row tmp(entries);
Kirill Terekhov's avatar
Kirill Terekhov committed
196
        expr.GetJacobian(-1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
197
198
        entries.Swap(tmp);
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
199
200
201
202
203
      return *this;
    }
    __INLINE multivar_expression & operator *=(basic_expression const & expr)
    {
      INMOST_DATA_REAL_TYPE lval = value, rval = expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
204
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
205
        AddBasicExpression(entries,rval,lval,expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
206
207
208
209
      else
      {
        Sparse::Row tmp(entries);
        for(Sparse::Row::iterator it = tmp.Begin(); it != tmp.End(); ++it) it->second *= rval;
Kirill Terekhov's avatar
Kirill Terekhov committed
210
        expr.GetJacobian(lval,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
211
212
        entries.Swap(tmp);
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
213
214
215
216
217
      value *= rval;
      return *this;
    }
    __INLINE multivar_expression & operator /=(basic_expression const & expr)
    {
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
218
      INMOST_DATA_REAL_TYPE rval = expr.GetValue();
Kirill Terekhov's avatar
Kirill Terekhov committed
219
220
      INMOST_DATA_REAL_TYPE reciprocial_rval = 1.0/rval;
      value *= reciprocial_rval;
Kirill Terekhov's avatar
Kirill Terekhov committed
221
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
222
        AddBasicExpression(entries,reciprocial_rval,-value*reciprocial_rval,expr);
Kirill Terekhov's avatar
Kirill Terekhov committed
223
224
225
226
      else
      {
        Sparse::Row tmp(entries);
        for(Sparse::Row::iterator it = tmp.Begin(); it != tmp.End(); ++it) it->second *= reciprocial_rval;
Kirill Terekhov's avatar
Kirill Terekhov committed
227
        expr.GetJacobian(-value*reciprocial_rval,tmp); 
Kirill Terekhov's avatar
Kirill Terekhov committed
228
229
        entries.Swap(tmp);
      }
Kirill Terekhov's avatar
Kirill Terekhov committed
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
      return *this;
    }
    __INLINE multivar_expression & operator +=(INMOST_DATA_REAL_TYPE right)
    {
      value += right;
      return *this;
    }
    __INLINE multivar_expression & operator -=(INMOST_DATA_REAL_TYPE right)
    {
      value -= right;
      return *this;
    }
    __INLINE multivar_expression & operator *=(INMOST_DATA_REAL_TYPE right)
    {
      value *= right;
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it) it->second *= right;
      return *this;
    }
    __INLINE multivar_expression & operator /=(INMOST_DATA_REAL_TYPE right)
    {
      value /= right;
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it) it->second /= right;
      return *this;
    }
    bool check_nans() const
    {
      if( value != value ) return true;
      for(Sparse::Row::const_iterator it = entries.Begin(); it != entries.End(); ++it)
        if( it->second != it->second ) return true;
      return false;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
    /// Write variable into array of entries.
    /// Size of array can be determined via RecordSize.
    /// Used internally by Mesh::GetData.
    /// @param v Array of entries that will store data of the variable.
    /// @return Number of entries used.
    INMOST_DATA_ENUM_TYPE Record(Sparse::Row::entry * v) const
    {
      INMOST_DATA_ENUM_TYPE k = 0;
      v[k].first = entries.Size();
      v[k].second = value;
      k++;
      for(INMOST_DATA_ENUM_TYPE r = 0; r < entries.Size(); ++r)
      {
        v[k].first = entries.GetIndex(r);
        v[k].second = entries.GetValue(r);
        k++;
      }
      return k;
    }
    /// Number of entries required to record the variable.
    INMOST_DATA_ENUM_TYPE RecordSize() const
    {
      return 1 + entries.Size();
    }
    /// Retrive variable from array of entries.
    /// Size of array without retrival can be determined via RetriveSize.
    /// @param v Array of entries that will store data of the variable.
    /// @return Number of entries red.
    INMOST_DATA_ENUM_TYPE Retrive(const Sparse::Row::entry * v)
    {
      int k = 0;
      value = v[k].second;
      entries.Resize(v[k].first);
      k++;
      for(int r = 0; r < (int)entries.Size(); ++r)
      {
        entries.GetIndex(r) = v[k].first;
        entries.GetValue(r) = v[k].second;
        k++;
      }
      return k;
    }
    /// Number of entries used.
    static INMOST_DATA_ENUM_TYPE RetriveSize(const Sparse::Row::entry * v)
    {
      return 1 + v[0].first;
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
308
309
  };

Kirill Terekhov's avatar
Kirill Terekhov committed
310
311
312
313
314
315
  
  class multivar_expression_reference : public shell_expression<multivar_expression_reference>
  {
    INMOST_DATA_REAL_TYPE & value;
    Sparse::Row & entries;
  public:
Kirill Terekhov's avatar
Kirill Terekhov committed
316
317
    void Lock() {entries.Lock();}
    void Unlock() {entries.Unlock();}
Kirill Terekhov's avatar
Kirill Terekhov committed
318
319
320
321
322
323
324
325
326
327
328
    /// Constructor, set links to the provided value and entries
    multivar_expression_reference(INMOST_DATA_REAL_TYPE & _value, Sparse::Row & _entries) 
      : value(_value), entries(_entries) {}
    /// Copy constructor, sets links to the same reference of value and entries
    multivar_expression_reference(const multivar_expression_reference & other) 
      : value(other.value), entries(other.entries) {}
    /// Retrive value
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
    /// Set value without changing derivatives
    __INLINE void SetValue(INMOST_DATA_REAL_TYPE val) { value = val; }
    /// Retrive derivatives with multiplier into Sparse::RowMerger structure.
Kirill Terekhov's avatar
Kirill Terekhov committed
329
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
330
331
332
333
334
    {
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it)
        r[it->first] += it->second*mult;
    }
    /// Retrive derivatives with multiplier into Sparse::Row structure.
Kirill Terekhov's avatar
Kirill Terekhov committed
335
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
336
337
    {
      if( CheckCurrentAutomatizator() )
Kirill Terekhov's avatar
Kirill Terekhov committed
338
        FromGetJacobian(*this,mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
      else
      {
        for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it)
          r[it->first] += it->second*mult;
      }
    }
    __INLINE multivar_expression_reference & operator = (INMOST_DATA_REAL_TYPE pvalue)
    {
      value = pvalue;
      entries.Clear();
      return *this;
    }
    __INLINE multivar_expression_reference & operator = (basic_expression const & expr)
    {
      value = expr.GetValue();
      if( CheckCurrentAutomatizator() )
        FromBasicExpression(entries,expr);
      else
      {
        Sparse::Row tmp;
Kirill Terekhov's avatar
Kirill Terekhov committed
359
        expr.GetJacobian(1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
        entries.Swap(tmp);
      }
      return *this;
    }
    __INLINE multivar_expression_reference & operator = (multivar_expression_reference const & other)
    {
      value = other.GetValue();
      entries = other.GetRow();
      return *this;
    }
    __INLINE multivar_expression_reference & operator = (multivar_expression const & other)
    {
      value = other.GetValue();
      entries = other.GetRow();
      return *this;
    }
    __INLINE Sparse::Row & GetRow() {return entries;}
    __INLINE const Sparse::Row & GetRow() const {return entries;}
    __INLINE multivar_expression_reference & operator +=(basic_expression const & expr)
    {
      value += expr.GetValue();
      if( CheckCurrentAutomatizator() )
        AddBasicExpression(entries,1.0,1.0,expr);
      else
      { 
        Sparse::Row tmp(entries);
Kirill Terekhov's avatar
Kirill Terekhov committed
386
        expr.GetJacobian(1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
387
388
389
390
391
392
393
394
395
396
397
398
        entries.Swap(tmp);
      }
      return *this;
    }
    __INLINE multivar_expression_reference & operator -=(basic_expression const & expr)
    {
      value -= expr.GetValue();
      if( CheckCurrentAutomatizator() )
        AddBasicExpression(entries,1.0,-1.0,expr);
      else
      {
        Sparse::Row tmp(entries);
Kirill Terekhov's avatar
Kirill Terekhov committed
399
        expr.GetJacobian(-1.0,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
400
401
402
403
404
405
406
407
408
409
410
411
412
        entries.Swap(tmp);
      }
      return *this;
    }
    __INLINE multivar_expression_reference & operator *=(basic_expression const & expr)
    {
      INMOST_DATA_REAL_TYPE lval = value, rval = expr.GetValue();
      if( CheckCurrentAutomatizator() )
        AddBasicExpression(entries,rval,lval,expr);
      else
      {
        Sparse::Row tmp(entries);
        for(Sparse::Row::iterator it = tmp.Begin(); it != tmp.End(); ++it) it->second *= rval;
Kirill Terekhov's avatar
Kirill Terekhov committed
413
        expr.GetJacobian(lval,tmp);
Kirill Terekhov's avatar
Kirill Terekhov committed
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
        entries.Swap(tmp);
      }
      value *= rval;
      return *this;
    }
    __INLINE multivar_expression_reference & operator /=(basic_expression const & expr)
    {
      INMOST_DATA_REAL_TYPE rval = expr.GetValue();
      INMOST_DATA_REAL_TYPE reciprocial_rval = 1.0/rval;
      value *= reciprocial_rval;
      if( CheckCurrentAutomatizator() )
        AddBasicExpression(entries,reciprocial_rval,-value*reciprocial_rval,expr);
      else
      {
        Sparse::Row tmp(entries);
        for(Sparse::Row::iterator it = tmp.Begin(); it != tmp.End(); ++it) it->second *= reciprocial_rval;
Kirill Terekhov's avatar
Kirill Terekhov committed
430
        expr.GetJacobian(-value*reciprocial_rval,tmp); 
Kirill Terekhov's avatar
Kirill Terekhov committed
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
        entries.Swap(tmp);
      }
      return *this;
    }
    __INLINE multivar_expression_reference & operator +=(INMOST_DATA_REAL_TYPE right)
    {
      value += right;
      return *this;
    }
    __INLINE multivar_expression_reference & operator -=(INMOST_DATA_REAL_TYPE right)
    {
      value -= right;
      return *this;
    }
    __INLINE multivar_expression_reference & operator *=(INMOST_DATA_REAL_TYPE right)
    {
      value *= right;
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it) it->second *= right;
      return *this;
    }
    __INLINE multivar_expression_reference & operator /=(INMOST_DATA_REAL_TYPE right)
    {
      value /= right;
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it) it->second /= right;
      return *this;
    }
    bool check_nans() const
    {
      if( value != value ) return true;
      for(Sparse::Row::iterator it = entries.Begin(); it != entries.End(); ++it)
        if( it->second != it->second ) return true;
      return false;
    }
  };
  

Kirill Terekhov's avatar
Kirill Terekhov committed
467
468
469
470
471
472
473
474
475
476
477
478
  template<class A>
  class const_multiplication_expression : public shell_expression<const_multiplication_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
  public:
    const_multiplication_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE pdmult) : arg(parg), dmult(pdmult)
    {
      value = arg.GetValue()*dmult;
    }
    const_multiplication_expression(const const_multiplication_expression & other) : arg(other.arg), value(other.value), dmult(other.dmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
479
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
480
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
481
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
482
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
483
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
484
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
485
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
    }
  };

  template<class A>
  class variation_multiplication_expression : public shell_expression<variation_multiplication_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
  public:
    variation_multiplication_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE pdmult) : arg(parg), dmult(pdmult)
    {
      value = arg.GetValue();
    }
    variation_multiplication_expression(const variation_multiplication_expression & other) : arg(other.arg), value(other.value), dmult(other.dmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
501
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
502
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
503
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
504
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
505
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
506
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
507
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
    }
  };


  template<class A>
  class const_division_expression : public shell_expression<const_division_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
  public:
    const_division_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE pdmult) : arg(parg), dmult(pdmult)
    {
      dmult = 1.0/dmult;
      value = arg.GetValue()*dmult;
    }
    const_division_expression(const const_division_expression & other) : arg(other.arg), value(other.value), dmult(other.dmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
525
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
526
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
527
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
528
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
529
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
530
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
531
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
    }
  };
  
  template<class A>
  class const_addition_expression : public shell_expression<const_addition_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value;
  public:
    const_addition_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE padd) : arg(parg)
    {
      value = arg.GetValue()+padd;
    }
    const_addition_expression(const const_addition_expression & other) : arg(other.arg), value(other.value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
547
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
548
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
549
      arg.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
550
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
551
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
552
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
553
      arg.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
    }
  };

  template<class A>
  class const_subtraction_expression : public shell_expression<const_subtraction_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value;
  public:
    const_subtraction_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE pleft) : arg(parg)
    {
      value = pleft-arg.GetValue();
    }
    const_subtraction_expression(const const_subtraction_expression & other) : arg(other.arg), value(other.value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
569
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
570
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
571
      arg.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
572
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
573
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
574
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
575
      arg.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
576
577
578
    }
  };

Kirill Terekhov's avatar
Kirill Terekhov committed
579
  /// c/x = -c dx / (x*x)
Kirill Terekhov's avatar
Kirill Terekhov committed
580
581
582
583
  template<class A>
  class reciprocal_expression : public shell_expression<reciprocal_expression<A> >
  {
    const A & arg;
Kirill Terekhov's avatar
Kirill Terekhov committed
584
    INMOST_DATA_REAL_TYPE value, reciprocial_val;
Kirill Terekhov's avatar
Kirill Terekhov committed
585
  public:
Kirill Terekhov's avatar
Kirill Terekhov committed
586
    reciprocal_expression(const shell_expression<A> & parg,INMOST_DATA_REAL_TYPE coef) : arg(parg)
Kirill Terekhov's avatar
Kirill Terekhov committed
587
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
588
589
      reciprocial_val = 1.0/arg.GetValue();
      value = coef*reciprocial_val;
Kirill Terekhov's avatar
Kirill Terekhov committed
590
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
591
592
    reciprocal_expression(const reciprocal_expression & other) 
      : arg(other.arg), value(other.value), reciprocial_val(other.reciprocial_val) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
593
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
594
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
595
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
596
      arg.GetJacobian(-mult*value*reciprocial_val,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
597
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
598
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
599
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
600
      arg.GetJacobian(-mult*value*reciprocial_val,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
601
602
603
604
605
606
607
608
609
610
611
612
    }
  };

  template<class A>
	class unary_minus_expression : public shell_expression<unary_minus_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value;
	public:
    unary_minus_expression(const shell_expression<A> & parg) : arg(parg) {value = -arg.GetValue();}
    unary_minus_expression(const unary_minus_expression & b) : arg(b.arg) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const {return value;}
Kirill Terekhov's avatar
Kirill Terekhov committed
613
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
614
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
615
      arg.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
616
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
617
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
618
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
619
      arg.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
    }
	};

  template<class A>
  class abs_expression : public shell_expression<abs_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    abs_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = arg.GetValue();
      dmult = value < 0.0 ? -1.0 : 1.0;
      value = ::fabs(value);
    }
    abs_expression(const abs_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const {return value;}
Kirill Terekhov's avatar
Kirill Terekhov committed
637
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
638
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
639
      arg.GetJacobian( mult * dmult, r);
Kirill Terekhov's avatar
Kirill Terekhov committed
640
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
641
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
642
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
643
      arg.GetJacobian( mult * dmult, r);
Kirill Terekhov's avatar
Kirill Terekhov committed
644
645
646
647
648
649
650
651
652
653
654
655
656
657
    }
	};

  template<class A>
	class exp_expression : public shell_expression<exp_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value;
	public:
    exp_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = arg.GetValue();
      value = ::exp(value);
    }
658
		exp_expression(const exp_expression & b) : arg(b.arg), value(b.value) {}
Kirill Terekhov's avatar
Kirill Terekhov committed
659
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
660
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
661
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
662
      arg.GetJacobian( mult * value, r);
Kirill Terekhov's avatar
Kirill Terekhov committed
663
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
664
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
665
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
666
      arg.GetJacobian( mult * value, r);
Kirill Terekhov's avatar
Kirill Terekhov committed
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
    }
  };

  template<class A>
	class log_expression : public shell_expression<log_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    log_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = arg.GetValue();
      dmult = 1.0/value;
      value = ::log(value);
    }
    log_expression(const log_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
684
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
685
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
686
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
687
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
688
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
689
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
690
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
    }
	};


  template<class A>
	class sin_expression : public shell_expression<sin_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    sin_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = arg.GetValue();
      dmult = ::cos(value);
      value = ::sin(value);
    }
    sin_expression(const sin_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
709
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
710
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
711
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
712
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
713
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
714
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
715
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
    }
	};

  template<class A>
	class cos_expression : public shell_expression<cos_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    cos_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = arg.GetValue();
      dmult = -(::sin(value));
      value = ::cos(value);
    }
    cos_expression(const cos_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
733
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
734
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
735
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
736
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
737
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
738
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
739
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
    }
	};

  template<class A>
	class sqrt_expression : public shell_expression<sqrt_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value;
	public:
    sqrt_expression(const shell_expression<A> & parg) : arg(parg) 
    {
      value = ::sqrt(arg.GetValue());
    }
    sqrt_expression(const sqrt_expression & b) : arg(b.arg), value(b.value) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
755
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
756
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
757
      arg.GetJacobian(0.5*mult/value,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
758
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
759
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
760
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
761
      arg.GetJacobian(0.5*mult/value,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
    }
	};


  template<class A>
	class soft_abs_expression : public shell_expression<soft_abs_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    soft_abs_expression(const shell_expression<A> & parg, INMOST_DATA_REAL_TYPE tol) : arg(parg) 
    {
      INMOST_DATA_REAL_TYPE lval = arg.GetValue();
      value = ::sqrt(lval*lval+tol*tol);
      dmult = lval/value;
    }
    soft_abs_expression(const soft_abs_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
780
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
781
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
782
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
783
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
784
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
785
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
786
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
    }
	};

  template<class A>
	class soft_sign_expression : public shell_expression<soft_sign_expression<A> >
	{
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
	public:
    soft_sign_expression(const shell_expression<A> & parg, INMOST_DATA_REAL_TYPE tol) : arg(parg) 
    {
      INMOST_DATA_REAL_TYPE lval = arg.GetValue(), lval2 = lval*lval;
      INMOST_DATA_REAL_TYPE div = lval2+tol*tol;
      INMOST_DATA_REAL_TYPE sdiv = ::sqrt(div);
      value = lval/sdiv;
      dmult = (1.0 - lval2/div)/sdiv;
    }
    soft_sign_expression(const soft_sign_expression & b) : arg(b.arg), value(b.value), dmult(b.dmult) {}
		__INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; };
Kirill Terekhov's avatar
Kirill Terekhov committed
806
		__INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
807
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
808
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
809
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
810
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const 
Kirill Terekhov's avatar
Kirill Terekhov committed
811
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
812
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
    }
	};

  template<class A, class B>
  class soft_max_expression : public shell_expression<soft_max_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value, ldmult, rdmult;
  public:
    soft_max_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright, INMOST_DATA_REAL_TYPE tol) : left(pleft), right(pright)
    {
      INMOST_DATA_REAL_TYPE lval = left.GetValue(), rval = right.GetValue();
      INMOST_DATA_REAL_TYPE diff = lval-rval, root = ::sqrt(diff*diff+tol*tol);
      value = 0.5*(lval+rval + root);
      ldmult = 0.5*(1 + diff/root);
      rdmult = 0.5*(1 - diff/root);
    }
    soft_max_expression(const soft_max_expression & other) 
      : left(other.left), right(other.right), value(other.value), ldmult(other.ldmult), rdmult(other.rdmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
834
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
835
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
836
837
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
838
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
839
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
840
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
841
842
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
    }
  };

  template<class A, class B>
  class soft_min_expression : public shell_expression<soft_min_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value, ldmult, rdmult;
  public:
    soft_min_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright, INMOST_DATA_REAL_TYPE tol) : left(pleft), right(pright)
    {
      INMOST_DATA_REAL_TYPE lval = left.GetValue(), rval = right.GetValue();
      INMOST_DATA_REAL_TYPE diff = lval-rval, root = ::sqrt(diff*diff+tol*tol);
      value = 0.5*(lval+rval - root);
      ldmult = 0.5*(1 - diff/root);
      rdmult = 0.5*(1 + diff/root);
    }
    soft_min_expression(const soft_min_expression & other) 
      : left(other.left), right(other.right), value(other.value), ldmult(other.ldmult), rdmult(other.rdmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
864
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
865
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
866
867
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
868
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
869
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
870
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
871
872
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
    }
  };


  template<class A, class B>
  class multiplication_expression : public shell_expression<multiplication_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value, ldmult, rdmult;
  public:
    multiplication_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright) : left(pleft), right(pright)
    {
      rdmult = left.GetValue();
      ldmult = right.GetValue();
      value = rdmult*ldmult;
    }
    multiplication_expression(const multiplication_expression & other) 
      : left(other.left), right(other.right), value(other.value), ldmult(other.ldmult), rdmult(other.rdmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
893
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
894
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
895
896
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
897
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
898
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
899
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
900
901
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
    }
  };

  template<class A, class B>
  class division_expression : public shell_expression<division_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value, reciprocal_rval;
  public:
    division_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright) : left(pleft), right(pright)
    {
      INMOST_DATA_REAL_TYPE lval = left.GetValue();
      INMOST_DATA_REAL_TYPE rval = right.GetValue();
      reciprocal_rval = 1.0 / rval;
      value = lval * reciprocal_rval;
    }
    division_expression(const division_expression & other) : left(other.left), right(other.right), value(other.value), reciprocal_rval(other.reciprocal_rval) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
921
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
922
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
923
924
      left.GetJacobian(mult * reciprocal_rval,r);
      right.GetJacobian(- mult * value * reciprocal_rval,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
925
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
926
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
927
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
928
929
      left.GetJacobian(mult * reciprocal_rval,r);
      right.GetJacobian(- mult * value * reciprocal_rval,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
    }
  };

  template<class A, class B>
  class addition_expression : public shell_expression<addition_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value;
  public:
    addition_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright) : left(pleft), right(pright) 
    {
      value = left.GetValue() + right.GetValue();
    }
    addition_expression(const addition_expression & other) 
      : left(other.left), right(other.right), value(other.value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
947
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
948
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
949
950
      left.GetJacobian(mult,r);
      right.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
951
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
952
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
953
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
954
955
      left.GetJacobian(mult,r);
      right.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
    }
  };

  template<class A, class B>
  class subtraction_expression : public shell_expression<subtraction_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value;
  public:
    subtraction_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright) : left(pleft), right(pright) 
    {
      value = left.GetValue() - right.GetValue();
    }
    subtraction_expression(const subtraction_expression & other) 
      : left(other.left), right(other.right),value(other.value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
973
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
974
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
975
976
      left.GetJacobian(mult,r);
      right.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
977
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
978
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
979
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
980
981
      left.GetJacobian(mult,r);
      right.GetJacobian(-mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
    }
  };

  template<class A, class B>
  class pow_expression : public shell_expression<pow_expression<A,B> >
  {
    const A & left;
    const B & right;
    INMOST_DATA_REAL_TYPE value, ldmult, rdmult;
  public:
    pow_expression(const shell_expression<A> & pleft, const shell_expression<B> & pright) : left(pleft), right(pright) 
    {
      INMOST_DATA_REAL_TYPE lval = left.GetValue();
      INMOST_DATA_REAL_TYPE rval = right.GetValue();
      value = ::pow(lval,rval);
      if( lval != 0 )
      {
        ldmult = value * rval / lval;
        rdmult = value * ::log(lval);
      }
      else
      {
        ldmult = 0;
        rdmult = 0;
      }
    }
    pow_expression(const pow_expression & other)
      :left(other.left), right(other.right), value(other.value), 
       ldmult(other.ldmult), rdmult(other.rdmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
1012
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1013
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1014
1015
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1016
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1017
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1018
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1019
1020
      left.GetJacobian(mult*ldmult,r);
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
    }
  };

  template<class A>
  class pow_const_expression : public shell_expression<pow_const_expression<A> >
  {
    const A & left;
    INMOST_DATA_REAL_TYPE value, ldmult;
  public:
    pow_const_expression(const shell_expression<A> & pleft, INMOST_DATA_REAL_TYPE pright) : left(pleft)
    {
      INMOST_DATA_REAL_TYPE lval = left.GetValue();
      value = ::pow(lval,pright);
      if( lval != 0 )
        ldmult = value * pright / lval;
      else
        ldmult = 0;
    }
    pow_const_expression(const pow_const_expression & other)
      :left(other.left), value(other.value), ldmult(other.ldmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
1042
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1043
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1044
      left.GetJacobian(mult*ldmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1045
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1046
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1047
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1048
      left.GetJacobian(mult*ldmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
    }
  };

  template<class A>
  class const_pow_expression : public shell_expression<const_pow_expression<A> >
  {
    const A & right;
    INMOST_DATA_REAL_TYPE value, rdmult;
  public:
    const_pow_expression(INMOST_DATA_REAL_TYPE pleft, const shell_expression<A> & pright) : right(pright) 
    {
      INMOST_DATA_REAL_TYPE rval = right.GetValue();
      value = ::pow(pleft,rval);
1062
1063
      if( pleft != 0 )
        rdmult = value * ::log(pleft);
Kirill Terekhov's avatar
Kirill Terekhov committed
1064
1065
1066
1067
1068
1069
      else
        rdmult = 0;
    }
    const_pow_expression(const const_pow_expression & other)
      :right(other.right), value(other.value), rdmult(other.rdmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
1070
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1071
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1072
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1073
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1074
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1075
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1076
      right.GetJacobian(mult*rdmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
    }
  };

  template<class A, class B, class C>
  class condition_expression : public shell_expression<condition_expression<A,B,C> >
  {
    const A & cond;
    const B & left;
    const C & right;
    INMOST_DATA_REAL_TYPE value, cond_value;
  public:
    condition_expression(const shell_expression<A> & pcond, const shell_expression<B> & pleft, const shell_expression<C> & pright) : cond(pcond), left(pleft), right(pright) 
    {
      cond_value = cond.GetValue();
      value = cond_value >= 0.0 ? left.GetValue() : right.GetValue();
    }
    condition_expression(const condition_expression & other)
      :cond(other.cond), left(other.left), right(other.right), 
      value(other.value), cond_value(other.cond_value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
1097
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1098
1099
    {
      if( cond_value >= 0.0 )
Kirill Terekhov's avatar
Kirill Terekhov committed
1100
        left.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1101
      else
Kirill Terekhov's avatar
Kirill Terekhov committed
1102
        right.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1103
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1104
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1105
1106
    {
      if( cond_value >= 0.0 )
Kirill Terekhov's avatar
Kirill Terekhov committed
1107
        left.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1108
      else
Kirill Terekhov's avatar
Kirill Terekhov committed
1109
        right.GetJacobian(mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
    }
  };

  template<class A> 
  class stencil_expression : public shell_expression<stencil_expression<A> >
  {
    dynarray< std::pair<INMOST_DATA_REAL_TYPE, A >, 64 > arg;
    INMOST_DATA_REAL_TYPE value;
  public:
    stencil_expression(const dynarray< std::pair<INMOST_DATA_REAL_TYPE, A >, 64 > & parg) : arg(parg) 
    {
      value = 0.0;
1122
      for(typename dynarray< std::pair<INMOST_DATA_REAL_TYPE, A >, 64 >::iterator it = arg.begin(); it != arg.end(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
1123
1124
1125
1126
        value += it->first * it->second.GetValue();
    }
    stencil_expression(const stencil_expression & other) : arg(other.arg), value(other.value) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const { return value; }
Kirill Terekhov's avatar
Kirill Terekhov committed
1127
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1128
    {
1129
      for(typename dynarray< std::pair<INMOST_DATA_REAL_TYPE, A >, 64 >::iterator it = arg.begin(); it != arg.end(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
1130
        it->second.GetJacobian(it->first*mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1131
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1132
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1133
    {
1134
      for(typename dynarray< std::pair<INMOST_DATA_REAL_TYPE, A >, 64 >::iterator it = arg.begin(); it != arg.end(); ++it)
Kirill Terekhov's avatar
Kirill Terekhov committed
1135
        it->second.GetJacobian(it->first*mult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1136
1137
1138
    }
  };

Kirill Terekhov's avatar
Kirill Terekhov committed
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152

  template<class A>
  class function_expression : public shell_expression< function_expression<A> >
  {
    const A & arg;
    INMOST_DATA_REAL_TYPE value, dmult;
  public:
    function_expression(const shell_expression<A> & _arg)
      :arg(_arg), value(1), dmult(0) {}
    function_expression(const shell_expression<A> & _arg, INMOST_DATA_REAL_TYPE pvalue, INMOST_DATA_REAL_TYPE pdmult)
      :arg(_arg), value(pvalue), dmult(pdmult) {}
    function_expression(const function_expression & other) 
      : arg(other.arg), value(other.value), dmult(other.dmult) {}
    __INLINE INMOST_DATA_REAL_TYPE GetValue() const {return value;}
Kirill Terekhov's avatar
Kirill Terekhov committed
1153
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::RowMerger & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1154
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1155
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1156
    }
Kirill Terekhov's avatar
Kirill Terekhov committed
1157
    __INLINE void GetJacobian(INMOST_DATA_REAL_TYPE mult, Sparse::Row & r) const
Kirill Terekhov's avatar
Kirill Terekhov committed
1158
    {
Kirill Terekhov's avatar
Kirill Terekhov committed
1159
      arg.GetJacobian(mult*dmult,r);
Kirill Terekhov's avatar
Kirill Terekhov committed
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
    }
    void SetFunctionValue(INMOST_DATA_REAL_TYPE val) {value = val;}
    void SetFunctionDerivative(INMOST_DATA_REAL_TYPE val) {value = val;}
  };

  
  class keyval_table
  {
    std::string name;
    INMOST_DATA_REAL_TYPE * vals;
    INMOST_DATA_REAL_TYPE * args;
    INMOST_DATA_ENUM_TYPE size;
    INMOST_DATA_ENUM_TYPE binary_search(INMOST_DATA_REAL_TYPE arg) const
	  {
		  int l = 0, r = static_cast<int>(size)-1, mid = 0;
		  while (r >= l)
		  {
			  mid = (l + r) / 2;
			  if (args[mid] > arg) r = mid - 1;
			  else if (args[mid] < arg) l = mid + 1;
			  else return mid;
		  }
		  mid = (l + r) / 2;
		  if (mid > static_cast<int>(size - 2)) mid = static_cast<int>(size - 2);
		  return static_cast<INMOST_DATA_ENUM_TYPE>(mid);
	  }
  public:
    INMOST_DATA_REAL_TYPE GetValue(INMOST_DATA_REAL_TYPE arg) const
	  {
		  if (arg < args[0]) return vals[0];
		  INMOST_DATA_ENUM_TYPE i = binary_search(arg);
		  return vals[i] + (vals[i + 1] - vals[i]) * (arg - args[i]) / (args[i + 1] - args[i]);
	  }
    INMOST_DATA_REAL_TYPE GetDerivative(INMOST_DATA_REAL_TYPE arg) const
	  {
		  if (arg < args[0]) return 0.0;
		  INMOST_DATA_ENUM_TYPE i = binary_search(arg);
		  return (vals[i + 1] - vals[i]) / (args[i + 1] - args[i]);
	  }
    std::pair<INMOST_DATA_REAL_TYPE, INMOST_DATA_REAL_TYPE> GetBoth(INMOST_DATA_REAL_TYPE arg) const
	  {
		  if (arg < args[0]) return std::make_pair(vals[0], 0.0);
		  INMOST_DATA_ENUM_TYPE i = binary_search(arg);
		  INMOST_DATA_REAL_TYPE der = (vals[i + 1] - vals[i]) / (args[i + 1] - args[i]);
		  return std::make_pair(vals[i] + der * (arg - args[i]), der);
	  }
    keyval_table() :name(""), vals(NULL), args(NULL), size(0) {}
    keyval_table(std::string _name, INMOST_DATA_REAL_TYPE * _args, INMOST_DATA_REAL_TYPE * _vals, INMOST_DATA_ENUM_TYPE _size)
    {
      name = _name;
      size = _size;
      vals = new INMOST_DATA_REAL_TYPE[size];
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1212
1213
      memcpy(vals,_vals,sizeof(INMOST_DATA_REAL_TYPE)*size);
      //std::copy(_vals,_vals+size,vals);
Kirill Terekhov's avatar
Kirill Terekhov committed
1214
      args = new INMOST_DATA_REAL_TYPE[size];
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1215
1216
      memcpy(args,_args,sizeof(INMOST_DATA_REAL_TYPE)*size);
      //std::copy(_args,_args+size,args);
Kirill Terekhov's avatar
Kirill Terekhov committed
1217
1218
1219
1220
1221
1222
    }
    keyval_table(const keyval_table & other)
    {
      name = other.name;
      size = other.size;
      vals = new INMOST_DATA_REAL_TYPE[size];
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1223
1224
      memcpy(vals,other.vals,sizeof(INMOST_DATA_REAL_TYPE)*size);
      //std::copy(other.vals,other.vals+size,vals);
Kirill Terekhov's avatar
Kirill Terekhov committed
1225
      args = new INMOST_DATA_REAL_TYPE[size];
Kirill Terekhov's avatar
Fixes    
Kirill Terekhov committed
1226
1227
      memcpy(args,other.args,sizeof(INMOST_DATA_REAL_TYPE)*size);
      //std::copy(other.args,other.args+size,args);
Kirill Terekhov's avatar
Kirill Terekhov committed
1228
1229
1230
1231
1232
1233
1234
    }
    keyval_table & operator = (keyval_table const & other)
    {
      Clear();
      name =