CVM Class Library  8.1
This C++ class library encapsulates concepts of vector and different matrices including square, band, symmetric and hermitian ones in Euclidean space of real and complex numbers.
 All Classes Files Functions Variables Typedefs Friends Macros Pages
cfun.h
Go to the documentation of this file.
1 // CVM Class Library
2 // http://cvmlib.com
3 //
4 // Copyright Sergei Nikolaev 1992-2014
5 // Distributed under the Boost Software License, Version 1.0.
6 // (See accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 
9 #ifndef _CFUN_H
10 #define _CFUN_H
11 
12 #include "cvm.h" // http://cvmlib.com
13 
14 #include <ctype.h>
15 #include <vector>
16 
17 #define CFUN_K_FUN 1
18 #define CFUN_K_VAR 2
19 #define CFUN_K_CONST 3
20 #define CFUN_K_PLUS 10
21 #define CFUN_K_MINUS 11
22 #define CFUN_K_MULT 12
23 #define CFUN_K_DIV 13
24 #define CFUN_K_POWER 14
25 #define CFUN_K_EXP 16
26 #define CFUN_K_SQRT 17
27 #define CFUN_K_LOG 18
28 #define CFUN_K_LOG10 19
29 #define CFUN_K_SIN 20
30 #define CFUN_K_COS 21
31 #define CFUN_K_TAN 22
32 #define CFUN_K_ARCSIN 23
33 #define CFUN_K_ARCCOS 24
34 #define CFUN_K_ARCTAN 25
35 #define CFUN_K_SINH 26
36 #define CFUN_K_COSH 27
37 #define CFUN_K_TANH 28
38 #define CFUN_K_UMINUS 29
39 #define CFUN_K_SIGN 30
40 #define CFUN_K_ABS 31
41 #define CFUN_K_DELTA 32
42 #define CFUN_K_INFINITY 33
43 #define CFUN_K_MNINFINITY 34
44 #define CFUN_K_INTSIN 35
45 #define CFUN_K_INTCOS 36
46 #define CFUN_K_SAT 37
47 #define CFUN_K_DSOLVE 38
48 #define CFUN_K_IIF 39
49 #define CFUN_O_BRACE '{'
50 #define CFUN_C_BRACE '}'
51 #define CFUN_O_BRACKET '['
52 #define CFUN_C_BRACKET ']'
53 #define CFUN_O_PARENTH '('
54 #define CFUN_C_PARENTH ')'
55 #define CFUN_O_SPARENTH "("
56 #define CFUN_C_SPARENTH ")"
57 #define CFUN_COMMA ','
58 #define CFUN_PLUS '+'
59 #define CFUN_MINUS '-'
60 #define CFUN_POWER '^'
61 #define CFUN_MULT '*'
62 #define CFUN_DIV '/'
63 #define CFUN_POINT '.'
64 #define CFUN_SIGNS "()+-^*/"
65 #define CFUN_INF "INF"
66 
67 #define CFUN_EXP "exp"
68 #define CFUN_SQRT "sqrt"
69 #define CFUN_LOG "log"
70 #define CFUN_LOG10 "log10"
71 #define CFUN_SIN "sin"
72 #define CFUN_COS "cos"
73 #define CFUN_TAN "tan"
74 #define CFUN_ASIN "asin"
75 #define CFUN_ACOS "acos"
76 #define CFUN_ATAN "atan"
77 #define CFUN_SINH "sinh"
78 #define CFUN_COSH "cosh"
79 #define CFUN_TANH "tanh"
80 #define CFUN_SI "sinint"
81 #define CFUN_CI "cosint"
82 #define CFUN_SMINUS "-"
83 #define CFUN_SPLUS "+"
84 #define CFUN_SMULT "*"
85 #define CFUN_SDIV "/"
86 #define CFUN_SPOWER "^"
87 #define CFUN_SCOMMA ","
88 #define CFUN_SSPACE " "
89 #define CFUN_SIGN "sign"
90 #define CFUN_ABS "abs"
91 #define CFUN_IIF "iif"
92 #define CFUN_DELTA "delta"
93 #define CFUN_POWERS "power"
94 #define CFUN_SAT "sat"
95 #define CFUN_I "i"
96 #define CFUN_SPACES " \t\r\n"
97 #define CFUN_SINF CFUN_O_SPARENTH CFUN_INF CFUN_C_SPARENTH
98 #define CFUN_SMINF CFUN_O_SPARENTH CFUN_SMINUS CFUN_INF CFUN_C_SPARENTH
99 
100 // find* functions failure code
101 #define CFUN_NOT_FOUND size_t(~0)
102 
103 #if defined (CVM_FLOAT)
104 # define CFUN_M_ZERO 0.F
105 # define CFUN_M_ONE 1.F
106 # define CFUN_M_TWO 2.F
107 # define CFUN_M_MONE -1.F
108 # define CFUN_M_HALF 0.5F
109 # define CFUN_M_E 2.7182818284590452353602874713527F
110 # define CFUN_M_LN2 0.69314718055994530941723212145818F
111 # define CFUN_M_PI 3.1415926535897932384626433832795F
112 # define CFUN_M_PI_2 1.5707963267948966192313216916398F
113 # define CFUN_M_LN_10 2.3025850929940456840179914546844F
114 # define CFUN_M_GAMMA 0.57721566490153286060651209008240243F
115 #else
116 # define CFUN_M_ZERO 0.L
117 # define CFUN_M_ONE 1.L
118 # define CFUN_M_TWO 2.L
119 # define CFUN_M_MONE -1.L
120 # define CFUN_M_HALF 0.5L
121 # define CFUN_M_E 2.7182818284590452353602874713527L
122 # define CFUN_M_LN2 0.69314718055994530941723212145818L
123 # define CFUN_M_PI 3.1415926535897932384626433832795L
124 # define CFUN_M_PI_2 1.5707963267948966192313216916398L
125 # define CFUN_M_LN_10 2.3025850929940456840179914546844L
126 # define CFUN_M_GAMMA 0.57721566490153286060651209008240243L
127 #endif
128 
129 #define CFUN_OK CVM_OK
130 #define CFUN_PARSEERROR CVM_THE_LAST_ERROR_CODE + 1
131 #define CFUN_DOMAINERROR CVM_THE_LAST_ERROR_CODE + 2
132 #define CFUN_DOMAINERROR_C CVM_THE_LAST_ERROR_CODE + 3
133 #define CFUN_CONVERGENCEERROR CVM_THE_LAST_ERROR_CODE + 4
134 #define CFUN_CONVERGENCEERROR_C CVM_THE_LAST_ERROR_CODE + 5
135 #define CFUN_SUBSTPARAMETERERROR CVM_THE_LAST_ERROR_CODE + 6
136 #define CFUN_VARSDONTMATCH CVM_THE_LAST_ERROR_CODE + 7
137 #define CFUN_NULLPOINTERERROR CVM_THE_LAST_ERROR_CODE + 8
138 #define CFUN_PARAMETER_RECURSION CVM_THE_LAST_ERROR_CODE + 9
139 
140 #define CFUN_SIMPS_STACK_DEPTH 32
141 #define CFUN_MAX_EI_ITERATIONS 1000
142 
143 
145 
146 
148 
149 // specializations for some elementary functions
150 template <typename T>
151 class ElementaryFunctions
152 {
153  typedef std::complex<T> TC;
154 
155 public:
156  static T asin(const T& v) throw(cvmexception)
157  {
158  if (v < CFUN_M_MONE || v > CFUN_M_ONE)
159  throw cvmexception(CFUN_DOMAINERROR, "asin", v);
160  return ::asin(v);
161  }
162  static T acos(const T& v) throw(cvmexception)
163  {
164  if (v < CFUN_M_MONE || v > CFUN_M_ONE)
165  throw cvmexception(CFUN_DOMAINERROR, "acos", v);
166  return ::acos(v);
167  }
168  static T tan(const T& v)
169  {
170  return ::tan(v);
171  }
172  static T atan(const T& v)
173  {
174  return ::atan(v);
175  }
176  static T sinh(const T& v)
177  {
178  return ::sinh(v);
179  }
180  static T cosh(const T& v)
181  {
182  return ::cosh(v);
183  }
184  static T tanh(const T& v)
185  {
186  return ::tanh(v);
187  }
188  static T sqrt(const T& v) throw(cvmexception)
189  {
190  if (v < CFUN_M_ZERO)
191  throw cvmexception(CFUN_DOMAINERROR, "sqrt", v);
192  return ::sqrt(v);
193  }
194  static T log(const T& v) throw(cvmexception)
195  {
196  if (v < cvm::basic_cvmMachMin<T>())
197  throw cvmexception(CFUN_DOMAINERROR, "log", v);
198  return ::log(v);
199  }
200  static T log10(const T& v) throw(cvmexception)
201  {
202  if (v < cvm::basic_cvmMachMin<T>())
203  throw cvmexception(CFUN_DOMAINERROR, "log", v);
204  return ::log10(v);
205  }
206  static T pow(const T& vBase, const T& vPower)
207  {
208  return ::pow(vBase, vPower);
209  }
210 
211  // Sine integral
212  static T sinint(const T& x, const T& eps) throw(cvmexception)
213  {
214  T si = CFUN_M_ZERO;
215  T xa = cvm::_abs(x);
216 
217  if (xa > CFUN_M_TWO) {
218  si = CFUN_M_PI_2 + e1(xa, eps).imag();
219  }
220  else {
221  si = xa;
222  if (xa > eps) {
223  T t;
224  T f = xa;
225  int sign = -1;
226  for (int i = 3; i < CFUN_MAX_EI_ITERATIONS; i += 2) {
227  f *= xa * xa / T((i - 1) * i);
228  t = f / T(i);
229  si += T(sign) * t;
230  sign = -sign;
231  if (t / cvm::_abs(si) < eps)
232  break;
233  if (i >= CFUN_MAX_EI_ITERATIONS - 2) {
234  throw cvmexception(CFUN_CONVERGENCEERROR, "sinint", x);
235  }
236  }
237  }
238  }
239  if (x < CFUN_M_ZERO) {
240  si = -si;
241  }
242  return si;
243  }
244 
245  // Cosine integral
246  static T cosint(const T& x, const T& eps) throw(cvmexception)
247  {
248  if (x <= CFUN_M_ZERO) {
249  throw cvmexception(CFUN_DOMAINERROR, "cosint", x);
250  }
251 
252  T ci = CFUN_M_ZERO;
253  if (x > CFUN_M_TWO) {
254  ci = -e1(x, eps).real();
255  }
256  else {
257  T t;
258  T f = CFUN_M_ONE;
259  int sign = -1;
260  for (int i = 2; i < CFUN_MAX_EI_ITERATIONS; i += 2) {
261  f *= x * x / T((i - 1) * i);
262  t = f / T(i);
263  ci += T(sign) * t;
264  sign = -sign;
265  if (t / cvm::_abs(ci) < eps)
266  break;
267  if (i >= CFUN_MAX_EI_ITERATIONS - 2) {
268  throw cvmexception(CFUN_CONVERGENCEERROR, "cosint", x);
269  }
270  }
271  ci += log(x) + CFUN_M_GAMMA;
272  }
273  return ci;
274  }
275 
276  // Exponential integral routine
277  static TC e1(const T& x, const T& eps) throw(cvmexception)
278  {
279  static const TC c1(CFUN_M_ONE, CFUN_M_ZERO);
280  static const TC c2(CFUN_M_TWO, CFUN_M_ZERO);
281  TC a;
282  TC b(CFUN_M_ONE, x);
283  TC c(CFUN_M_ONE / (eps * eps), CFUN_M_ZERO);
284  TC d(c1 / b);
285  TC e(d);
286 
287  for (int i = 1; i < CFUN_MAX_EI_ITERATIONS; ++i) {
288  a = TC(T(-i * i), CFUN_M_ZERO);
289  b += c2;
290  d = c1 / (a * d + b);
291  c = b + a / c;
292  a = c * d;
293  e *= a;
294  if (cvm::_abs(CFUN_M_ONE - a.real()) + cvm::_abs(a.imag()) < eps)
295  break;
296  if (i >= CFUN_MAX_EI_ITERATIONS - 1) {
297  throw cvmexception(CFUN_CONVERGENCEERROR, "ElementaryFunctions<T>::e1", x);
298  }
299  }
300  return TC(cos(x), -sin(x)) * e;
301  }
302 };
303 
304 template <typename T>
305 class ElementaryFunctions<std::complex<T> >
306 {
307  typedef std::complex<T> TC;
308 public:
309  static TC asin(const TC& v)
310  {
311  static const TC c1(CFUN_M_ONE, CFUN_M_ZERO);
312  static const TC cmi(CFUN_M_ZERO, CFUN_M_MONE);
313  return cmi * std::log(std::sqrt(c1 - v * v) - cmi * v);
314  }
315  static TC acos(const TC& v)
316  {
317  static const TC c1(CFUN_M_ONE, CFUN_M_ZERO);
318  static const TC cmi(CFUN_M_ZERO, CFUN_M_MONE);
319  return cmi * std::log(v - cmi * std::sqrt(c1 - v * v));
320  }
321  static TC tan(const TC& v)
322  {
323  const T rm = v.real() * CFUN_M_TWO;
324  const T im = v.imag() * CFUN_M_TWO;
325  if (cvm::_abs(im) >= basic_cvmLogMachMax<T>()) {
326  return TC(CFUN_M_ZERO, im > CFUN_M_ZERO ? CFUN_M_ONE : CFUN_M_MONE);
327  }
328  else {
329  const T d = ::cos(rm) + ::cosh(im);
330  return TC(::sin(rm) / d, ::sinh(im) / d);
331  }
332  }
333  static TC atan(const TC& v)
334  {
335  static const TC ci(CFUN_M_ZERO, CFUN_M_ONE);
336  static const TC ci2(CFUN_M_ZERO, CFUN_M_HALF);
337  return ci2 * std::log((ci + v) / (ci - v));
338  }
339  static TC sinh(const TC& v)
340  {
341  return std::sinh(v);
342  }
343  static TC cosh(const TC& v)
344  {
345  return std::cosh(v);
346  }
347  static TC tanh(const TC& v)
348  {
349  return std::tanh(v);
350  }
351  static TC sqrt(const TC& v)
352  {
353  return std::sqrt(v);
354  }
355  static TC log(const TC& v)
356  {
357  return std::log(v);
358  }
359  static TC log10(const TC& v)
360  {
361  return std::log10(v);
362  }
363  static TC pow(const TC& vBase, const TC& vPower)
364  {
365  return std::pow(vBase, vPower);
366  }
367 
368  // Sine integral
369  static TC sinint(const TC& x, const T& eps) throw(cvmexception)
370  {
371  TC si(x);
372  if (cvm::_abs(x) > eps) {
373  TC t;
374  TC f(x);
375  int sign = -1;
376  for (int i = 3; i < CFUN_MAX_EI_ITERATIONS; i += 2) {
377  f *= x * x / T((i - 1) * i);
378  t = f / T(i);
379  si += t * T(sign);
380  sign = -sign;
381  if (cvm::_abs(t) / cvm::_abs(si) < eps)
382  break;
383  if (i >= CFUN_MAX_EI_ITERATIONS - 2) {
384  throw cvmexception(CFUN_CONVERGENCEERROR_C, "sinint", x.real(), x.imag());
385  }
386  }
387  }
388  return si;
389  }
390 
391  // Cosine integral
392  static TC cosint(const TC& x, const T& eps) throw(cvmexception)
393  {
394  static const TC gamma(CFUN_M_GAMMA, CFUN_M_ZERO);
395  if (cvm::_abs(x) < eps) {
396  throw cvmexception(CFUN_DOMAINERROR_C, "cosint", x.real(), x.imag());
397  }
398 
399  TC ci(CFUN_M_ZERO);
400  TC t;
401  TC f(CFUN_M_ONE);
402  int sign = -1;
403  for (int i = 2; i < CFUN_MAX_EI_ITERATIONS; i += 2) {
404  f *= x * x / T((i - 1) * i);
405  t = f / T(i);
406  ci += t * T(sign);
407  sign = -sign;
408  if (cvm::_abs(t) / cvm::_abs(ci) < eps)
409  break;
410  if (i >= CFUN_MAX_EI_ITERATIONS - 2) {
411  throw cvmexception(CFUN_CONVERGENCEERROR_C, "cosint", x.real(), x.imag());
412  }
413  }
414  return ci + log(x) + gamma;
415  }
416 };
417 
418 
419 // cross-type stuff
420 template <typename T1, typename T2>
421 class Comparator
422 {
423 public:
424  static bool lt(const T1& l, const T2& r);
425  static bool le(const T1& l, const T2& r);
426  static bool gt(const T1& l, const T2& r);
427  static bool ge(const T1& l, const T2& r);
428  static bool eq(const T1& l, const T2& r);
429 };
430 
431 
437 template <typename T>
438 class shared_ptr_pair
439 {
440  std::shared_ptr<T> mp1;
441  std::shared_ptr<T> mp2;
442 public:
443 
449  shared_ptr_pair(T* p1, T* p2)
450  : mp1(p1),
451  mp2(p2)
452  {
453  }
454 
460  shared_ptr_pair(const std::shared_ptr<T>& p1, const std::shared_ptr<T>& p2)
461  : mp1(p1),
462  mp2(p2)
463  {
464  }
465 
471  shared_ptr_pair(std::shared_ptr<T>&& p1, std::shared_ptr<T>&& p2)
472  : mp1(std::move(p1)),
473  mp2(std::move(p2))
474  {
475  }
476 
482  std::shared_ptr<T> operator[](size_t i) throw(cvmexception)
483  {
484  if (i == 0) {
485  return mp1;
486  }
487  else if (i == 1) {
488  return mp2;
489  }
490  throw cvmexception(CVM_INDEX_GT, i, 1);
491  }
492 };
494 
495 
496 typedef std::vector<std::string> string_array;
497 
498 
500 inline size_t __not(size_t i)
501 {
502  return i ? 0 : 1;
503 }
504 
505 inline void __clean_array(string_array& a)
506 {
507  if (a.size() > 0) {
508  a.erase(a.begin(), a.end());
509  }
510 }
511 
512 template <typename T>
513 inline bool __parse_num(const std::string& s, T& result)
514 {
515  bool ret = true;
516  char* stop;
517  result = T(::strtod(s.c_str(), &stop));
518  if ((result == CFUN_M_ZERO && s[0] != '0') || result == HUGE_VAL || result == -HUGE_VAL || *stop != '\0') {
519  ret = false;
520  }
521  return ret;
522 }
523 
524 // 7.0 FIX: these big things must be inlined too!
525 // MS doesn't like to do memory allocation and deallocation in different versions of RTL.
526 // Therefore, to make it possible to mix MSVS 2012 and 2010 generated code we have to inline this stuff.
527 
528 inline std::string::const_iterator __trim_beg(const std::string& s, size_t nEdge = 0)
529 {
530  static const char szSpaces[] = CFUN_SPACES;
531  std::string::const_iterator it = s.end();
532  size_t nLen = s.length();
533 
534  if (nLen > nEdge * 2) { // both sides
535  nLen = s.find_first_not_of(szSpaces, nEdge);
536 
537  if (nLen != CFUN_NOT_FOUND) {
538  it = s.begin() + nLen;
539  }
540  }
541  return it;
542 }
543 
544 inline std::string::const_iterator __trim_end(const std::string& s, size_t nEdge = 0)
545 {
546  static const char szSpaces[] = CFUN_SPACES;
547  std::string::const_iterator it = s.end();
548  size_t nLen = s.length();
549 
550  if (nLen > nEdge * 2) { // both sides
551  nLen = s.find_last_not_of(szSpaces, nLen - nEdge - 1);
552 
553  if (nLen != CFUN_NOT_FOUND) {
554  it = s.begin() + (nLen + 1);
555  }
556  }
557  return it;
558 }
559 
560 // returns false if empty
561 inline bool __strip_parenth(const std::string& s, size_t& nFirst, size_t& nLast)
562 {
563  static const char szSpaces[] = CFUN_SPACES;
564  static const std::string sSigns(CFUN_SIGNS);
565  bool bRet = true;
566  int nLevel;
567  char c;
568  const size_t nLastOld = nLast;
569  if (s.length() <= nLast || (s[nLast] && sSigns.find(s[nLast]) != CFUN_NOT_FOUND)) {
570  --nLast;
571  }
572 
573  for (;;) {
574  nFirst = s.find_first_not_of(szSpaces, nFirst);
575  nLast = s.find_last_not_of(szSpaces, nLast);
576  if (nFirst == CFUN_NOT_FOUND || nLast == CFUN_NOT_FOUND) {
577  bRet = false;
578  break;
579  }
580  if (s[nFirst] == CFUN_O_PARENTH && s[nLast] == CFUN_C_PARENTH) { // if (xxxxx)
581  nLevel = 1;
582  for (size_t i = nFirst + 1; i < nLast; i++) { // but like (x) + (y) or (x*(2+y)-3)
583  c = s[i];
584  if (c == CFUN_C_PARENTH) {
585  nLevel--;
586  if (!nLevel)
587  break;
588  }
589  if (c == CFUN_O_PARENTH) {
590  nLevel++;
591  }
592  }
593  if (nLevel) {
594  nFirst++;
595  nLast--;
596  continue;
597  }
598  break;
599  }
600  else {
601  break;
602  }
603  }
604  if (nLastOld > nLast) {
605  ++nLast; // -> '\0'
606  }
607  return bRet;
608 }
609 
610 inline size_t __tassign(std::string& sDest, const std::string& sSrc, size_t nFirst, size_t nLast)
611 {
612  size_t nRet = 0;
613  if (__strip_parenth(sSrc, nFirst, nLast)) {
614  if (&sDest == &sSrc) {
615  if (nLast < sDest.length()) {
616  sDest.erase(sDest.begin() + nLast, sDest.end());
617  }
618  if (nFirst) {
619  sDest.erase(sDest.begin(), sDest.begin() + nFirst);
620  }
621  }
622  else {
623  sDest.assign(sSrc.begin() + nFirst, sSrc.begin() + nLast);
624  }
625  nRet = nLast - nFirst;
626  }
627  else {
628  sDest.erase();
629  }
630  return nRet;
631 }
632 
633 // "(x, 2)" -> "x" and "2"
634 // 0 - empty string
635 // 1 - there was a comma
636 // 2 - there wasn't a comma
637 inline int __separate(const std::string& sBody, size_t nFirst, size_t nLast,
638  std::string& sLeft, std::string& sRight)
639 {
640  if (__strip_parenth(sBody, nFirst, nLast)) {
641  size_t nOPos = sBody.find(CFUN_O_PARENTH, nFirst);
642  size_t nCPos = sBody.find(CFUN_C_PARENTH, nFirst);
643 
644  size_t i = nFirst;
645  for (;;) {
646  i = sBody.find(CFUN_COMMA, i);
647  if (i == CFUN_NOT_FOUND) {
648  __tassign(sLeft, sBody, nFirst, nLast);
649  sRight.erase();
650  return 2;
651  }
652  if (nOPos == CFUN_NOT_FOUND ||
653  nCPos == CFUN_NOT_FOUND ||
654  (nCPos > nOPos && (i < nOPos || i > nCPos))) {
655  __tassign(sLeft, sBody, nFirst, i);
656  __tassign(sRight, sBody, i + 1, nLast);
657  return 1;
658  }
659  i++;
660  }
661  }
662  sLeft.erase();
663  sRight.erase();
664  return 0;
665 }
666 
667 inline void __push_back_unique(string_array& a, const std::string& v)
668 {
669  string_array::const_iterator it = a.begin();
670  string_array::const_iterator end = a.end();
671  while (it != end) {
672  if ((*it) == v)
673  return;
674  ++it;
675  }
676  a.push_back(v);
677 }
678 
679 inline bool __arrays_equal(const string_array& a1, const string_array& a2)
680 {
681  bool ret = a1.size() == a2.size();
682  if (ret) {
683  string_array::const_iterator i1 = a1.begin();
684  string_array::const_iterator e1 = a1.end();
685  string_array::const_iterator i2 = a2.begin();
686  while (i1 != e1) {
687  if ((*i1) != (*i2)) {
688  ret = false;
689  break;
690  }
691  ++i1;
692  ++i2;
693  }
694  }
695  return ret;
696 }
697 
698 inline void __add_to_array(string_array& a, const std::string& sSrc,
699  std::string::const_iterator iBeg, std::string::const_iterator iEnd)
700 {
701  static const char szSpaces[] = CFUN_SPACES;
702  if (iEnd > iBeg) {
703  size_t nFirst = sSrc.find_first_not_of(szSpaces, iBeg - sSrc.begin());
704 
705  if (nFirst != CFUN_NOT_FOUND) {
706  size_t nLast = sSrc.find_last_not_of(szSpaces, iEnd - sSrc.begin() - 1);
707 
708  if (nLast != CFUN_NOT_FOUND &&
709  nLast >= nFirst) {
710  a.push_back(std::string(sSrc.begin() + nFirst, sSrc.begin() + (nLast + 1)));
711  }
712  }
713  }
714 }
715 
716 inline void __parse_vars(const std::string& sVars, size_t nFirst, size_t nLast, string_array& saResult)
717 {
718  size_t nL;
719  __clean_array(saResult);
720  for (;;) {
721  nL = sVars.find(CFUN_COMMA, nFirst);
722  if (nL == CFUN_NOT_FOUND || nL >= nLast) {
723  __add_to_array(saResult, sVars, sVars.begin() + nFirst, sVars.begin() + nLast);
724  break;
725  }
726  __add_to_array(saResult, sVars, sVars.begin() + nFirst, sVars.begin() + nL);
727  nFirst = nL + 1;
728  }
729 }
730 
731 inline std::string __format_vars(const string_array& a, bool emptyBraces = true)
732 {
733  std::stringstream stream;
734  bool showBraces = emptyBraces || a.size() > 0;
735  if (showBraces) {
736  stream << CFUN_O_BRACE;
737  }
738  string_array::const_iterator it = a.begin();
739  string_array::const_iterator end = a.end();
740  while (it != end) {
741  stream << *it;
742  ++it;
743  if (it != end)
744  stream << CFUN_SCOMMA;
745  }
746  if (showBraces) {
747  stream << CFUN_C_BRACE;
748  }
749  return stream.str();
750 }
751 
752 // MAC is missing isalpha while linking...
753 inline int is_alpha(int c)
754 {
755 #if defined (MAC)
756  if ((c >= 0141 && c <= 0172) || (c >= 0101 && c <= 0132)) {
757  return 1;
758  }
759  return 0;
760 #else
761  return isalpha(c);
762 #endif
763 }
764 
765 // k*x & k=a+b ---> (a+b)*x
766 inline bool __subst_parameter(std::string& sBody, const string_array& saParameters,
767  const string_array& saMeanings) throw(cvmexception)
768 {
769  bool ret = false;
770  const size_t nPsz = saParameters.size();
771 
772  for (size_t i = 0; i < nPsz; i++) {
773  if (sBody == saParameters[i]) {
774  ret = true;
775  if (i < saMeanings.size()) {
776  const std::string& sMeaning = saMeanings[i];
777  size_t nBeg = sMeaning.find_first_of(sBody);
778  if (nBeg != CFUN_NOT_FOUND) {
779  size_t nEnd = nBeg + sBody.length();
780  if ((nBeg <= 0 || !is_alpha(sMeaning.at(nBeg - 1))) && // p -> {p+p} || p -> {2*p-x} || p -> {22-p}
781  (nEnd >= sMeaning.length() || !is_alpha(sMeaning.at(nEnd)))) {
782 // if ((nBeg <= 0 || !isalpha(sMeaning.at(nBeg - 1))) && // p -> {p+p} || p -> {2*p-x} || p -> {22-p}
783 // (nEnd >= sMeaning.length() || !isalpha(sMeaning.at(nEnd)))) {
784  throw cvmexception(CFUN_PARAMETER_RECURSION, sBody.c_str(), sMeaning.c_str());
785  }
786  }
787  sBody.assign(__trim_beg(sMeaning), __trim_end(sMeaning));
788  }
789  else {
790  throw cvmexception(CFUN_SUBSTPARAMETERERROR, sBody.c_str());
791  }
792  break;
793  }
794  }
795  return ret;
796 }
797 
798 // returns true if body looks like 1.e+12 or 1.e-12
799 inline bool __ifbodynum(const std::string& sBody, size_t nBodyLength, size_t nSignPos)
800 {
801  static const char ccExp = 'e', ccExpb = 'E', ccPoint = '.';
802  return nSignPos < nBodyLength - 1 &&
803  isdigit(sBody[nSignPos + 1]) &&
804  nSignPos > 1 &&
805  (sBody[nSignPos - 1] == ccExp || sBody[nSignPos - 1] == ccExpb) &&
806  (sBody[nSignPos - 2] == ccPoint || isdigit(sBody[nSignPos - 2]));
807 }
808 
809 inline size_t __tassign(std::string& sDest, const std::string& sSrc, size_t nFirst)
810 {
811  return __tassign(sDest, sSrc, nFirst, sSrc.length());
812 }
813 
814 inline size_t __tassign(std::string& sDest, const std::string& sSrc)
815 {
816  return __tassign(sDest, sSrc, 0, sSrc.length());
817 }
818 
819 template <typename T> class BaseFunction;
820 template <typename T> class UnaryFunction;
821 template <typename T> class BinaryFunction;
822 template <typename T> class Fconst;
823 template <typename T> class Finfinity;
824 template <typename T> class Fmninfinity;
825 template <typename T> class Fplus;
826 template <typename T> class Fminus;
827 template <typename T> class Fmult;
828 template <typename T> class Fdiv;
829 template <typename T> class Fpower;
830 template <typename T> class Fsat;
831 template <typename T> class Fexp;
832 template <typename T> class Fsqrt;
833 template <typename T> class Flog;
834 template <typename T> class Flog10;
835 template <typename T> class Fsin;
836 template <typename T> class Fcos;
837 template <typename T> class Ftan;
838 template <typename T> class Fasin;
839 template <typename T> class Facos;
840 template <typename T> class Fatan;
841 template <typename T> class Fsinh;
842 template <typename T> class Fcosh;
843 template <typename T> class Ftanh;
844 template <typename T> class Fsinint;
845 template <typename T> class Fcosint;
846 template <typename T> class Fuminus;
847 template <typename T> class Fsign;
848 template <typename T> class Fabs;
849 template <typename T> class Fdelta;
850 template <typename T> class Fvar;
851 template <typename T> class Fiif;
852 
853 #ifdef CVM_USE_VARIADIC_TEMPLATES
854 # define CFUN_NEW_FUNC(cls, ...) std::make_shared<cls<T>>(__VA_ARGS__)
855 #else
856 # define CFUN_NEW_FUNC(cls, ...) BasePointer(new cls<T>(__VA_ARGS__))
857 #endif
858 
860 
861 
868 template <typename T>
870 {
871 public:
872  typedef typename std::shared_ptr<BaseFunction<T>> BasePointer;
873 
879  static BasePointer compile(const std::string& sPar, size_t nFirst, size_t nLast,
880  const string_array& saVars,
881  const string_array& saParameters,
882  const string_array& saMeanings,
883  bool subst = true) throw(cvmexception)
884  {
885  size_t i;
886  static const char pccSigns[] = CFUN_SIGNS;
887  static const char pccInfinity[] = CFUN_INF;
888  std::string sBody, sLeft;
889  size_t nBodyLength = __tassign(sBody, sPar, nFirst, nLast);
890 
891  if (!nBodyLength) {
892  throw cvmexception(CFUN_PARSEERROR, sPar.c_str(), __format_vars(saVars).c_str());
893  }
894 
895  // trying to handle real or complex number first
896  BasePointer pfConst = CFUN_NEW_FUNC(Fconst, sBody, false); // std::make_shared<Fconst<T>>(sBody, false);
897  if (pfConst->is_valid()) {
898  return pfConst;
899  }
900 
901  if (subst && __subst_parameter(sBody, saParameters, saMeanings)) { // k*x & k=a+b ---> (a+b)*x
902  return FunctionFactory<T>::compile(sBody, 0, sBody.length(), saVars, saParameters, saMeanings, false);
903  }
904 
905  int nLevel = 0;
906  for (i = nBodyLength - 1; i < CFUN_NOT_FOUND; --i) {
907  switch (sBody[i]) {
908  case CFUN_O_PARENTH:
909  ++nLevel;
910  break;
911  case CFUN_C_PARENTH:
912  --nLevel;
913  break;
914  case CFUN_PLUS:
915  if (!nLevel) {
916  if (!i) { // +x -> x
917  return FunctionFactory<T>::compile(sBody, 1, nBodyLength, saVars, saParameters, saMeanings, subst);
918  }
919  if (__ifbodynum(sBody, nBodyLength, i)) {
920  break;
921  }
922  return CFUN_NEW_FUNC(Fplus, sBody, 0, i, i + 1, nBodyLength, saVars, saParameters, saMeanings);
923  }
924  break;
925  case CFUN_MINUS:
926  if (!nLevel) {
927  if (__ifbodynum(sBody, nBodyLength, i)) {
928  break;
929  }
930  if (!i) {
931  return CFUN_NEW_FUNC(Fuminus, sBody, 1, nBodyLength, saVars, saParameters, saMeanings);
932  }
933  return CFUN_NEW_FUNC(Fminus, sBody, 0, i, i + 1, nBodyLength, saVars, saParameters, saMeanings);
934  }
935  break;
936  default:
937  break;
938  }
939  }
940  if (nLevel) { // ((...) or (...))
941  throw cvmexception(CFUN_PARSEERROR, sBody.c_str(), __format_vars(saVars).c_str());
942  }
943 
944  for (i = nBodyLength - 1; i < CFUN_NOT_FOUND; --i) {
945  switch (sBody[i]) {
946  case CFUN_O_PARENTH:
947  ++nLevel;
948  break;
949  case CFUN_C_PARENTH:
950  --nLevel;
951  break;
952  case CFUN_MULT: // x * y
953  if (!i) {
954  throw cvmexception(CFUN_PARSEERROR, sBody.c_str(), __format_vars(saVars).c_str());
955  }
956  if (!nLevel) {
957  return CFUN_NEW_FUNC(Fmult, sBody, 0, i, i + 1, nBodyLength, saVars, saParameters, saMeanings);
958  }
959  break;
960  case CFUN_DIV: // x / y
961  if (!i) {
962  throw cvmexception(CFUN_PARSEERROR, sBody.c_str(), __format_vars(saVars).c_str());
963  }
964  if (!nLevel) {
965  return CFUN_NEW_FUNC(Fdiv, sBody, 0, i, i + 1, nBodyLength, saVars, saParameters, saMeanings);
966  }
967  break;
968  default:
969  break;
970  }
971  }
972 
973  for (i = 0; i < nBodyLength; ++i) {
974  switch (sBody[i]) {
975  case CFUN_O_PARENTH:
976  ++nLevel;
977  break;
978  case CFUN_C_PARENTH:
979  --nLevel;
980  break;
981  case CFUN_POWER: // x ^ y
982  if (!i) {
983  throw cvmexception(CFUN_PARSEERROR, sBody.c_str(), __format_vars(saVars).c_str());
984  }
985  if (!nLevel) {
986  return CFUN_NEW_FUNC(Fpower, sBody, 0, i, i + 1, nBodyLength, saVars, saParameters, saMeanings);
987  }
988  break;
989  default:
990  break;
991  }
992  }
993 
994  if (isdigit(sBody[0]) || sBody[0] == CFUN_POINT) { // 1.e-3 or .2e+12 or 99
995  return CFUN_NEW_FUNC(Fconst, sBody);
996  }
997  if (sBody == pccInfinity) {
998  return CFUN_NEW_FUNC(Finfinity);
999  }
1000  for (i = 0; i < saVars.size(); ++i) {
1001  if (saVars[i] == sBody) {
1002  return std::make_shared<Fvar<T>>(sBody, i);
1003  }
1004  }
1005 
1006  size_t nLeft = sBody.find_first_of(pccSigns, 0); // sin(... cos(... etc. or x1 or y
1007  __tassign(sLeft, sBody, 0, nLeft);
1008 
1009  if (sLeft.length() == 0) {
1010  throw cvmexception(CFUN_PARSEERROR, sBody.c_str(), __format_vars(saVars).c_str());
1011  }
1012 
1013  if (sLeft == CFUN_EXP)
1014  return CFUN_NEW_FUNC(Fexp, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1015  else if (sLeft == CFUN_SQRT)
1016  return CFUN_NEW_FUNC(Fsqrt, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1017  else if (sLeft == CFUN_LOG)
1018  return CFUN_NEW_FUNC(Flog, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1019  else if (sLeft == CFUN_LOG10)
1020  return CFUN_NEW_FUNC(Flog10, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1021  else if (sLeft == CFUN_SIN)
1022  return CFUN_NEW_FUNC(Fsin, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1023  else if (sLeft == CFUN_COS)
1024  return CFUN_NEW_FUNC(Fcos, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1025  else if (sLeft == CFUN_TAN)
1026  return CFUN_NEW_FUNC(Ftan, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1027  else if (sLeft == CFUN_ASIN)
1028  return CFUN_NEW_FUNC(Fasin, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1029  else if (sLeft == CFUN_ACOS)
1030  return CFUN_NEW_FUNC(Facos, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1031  else if (sLeft == CFUN_ATAN)
1032  return CFUN_NEW_FUNC(Fatan, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1033  else if (sLeft == CFUN_SINH)
1034  return CFUN_NEW_FUNC(Fsinh, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1035  else if (sLeft == CFUN_COSH)
1036  return CFUN_NEW_FUNC(Fcosh, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1037  else if (sLeft == CFUN_TANH)
1038  return CFUN_NEW_FUNC(Ftanh, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1039  else if (sLeft == CFUN_SI)
1040  return CFUN_NEW_FUNC(Fsinint, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1041  else if (sLeft == CFUN_CI)
1042  return CFUN_NEW_FUNC(Fcosint, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1043  else if (sLeft == CFUN_SIGN)
1044  return CFUN_NEW_FUNC(Fsign, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1045  else if (sLeft == CFUN_ABS)
1046  return CFUN_NEW_FUNC(Fabs, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1047  else if (sLeft == CFUN_IIF)
1048  return CFUN_NEW_FUNC(Fiif, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1049  else if (sLeft == CFUN_DELTA)
1050  return CFUN_NEW_FUNC(Fdelta, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1051  else if (sLeft == CFUN_POWERS)
1052  return CFUN_NEW_FUNC(Fpower, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1053  else if (sLeft == CFUN_SAT)
1054  return CFUN_NEW_FUNC(Fsat, sBody, nLeft, nBodyLength, saVars, saParameters, saMeanings);
1055  else if (sLeft == CFUN_I)
1056  return CFUN_NEW_FUNC(Fconst, T(1));
1057  else
1058  throw cvmexception(CFUN_PARSEERROR, sLeft.c_str(), __format_vars(saVars).c_str());
1059  return CFUN_NEW_FUNC(Fconst, T(0));
1060  }
1061 };
1062 
1063 
1070 template <typename T>
1072 {
1073 protected:
1075 
1077  virtual BasePointer _simpl() const = 0; // returns simplified function as a new object
1078  virtual int _depth(bool) const = 0; // call stack acquire and release
1080 
1081 public:
1088  {
1089  }
1090 
1094  virtual ~BaseFunction()
1095  {
1096  }
1097 
1099  virtual int _kind() const = 0; // a kind of function type id
1100  virtual T _value(const T* pdVars) const = 0; // value of scalar function of few variables
1101  virtual BasePointer _clone() const = 0; // a new clone of an object
1102  virtual BasePointer _deriv(size_t nVarNum) const = 0; // _derivative by given variable as a new object
1103  virtual bool _equals(const BasePointer& pfSrc) const = 0; // checks whether they are identical
1104  virtual std::string _format(int nPrecision) const = 0; // returns formatted body
1105 
1106  virtual bool is_valid() const { // to override in FConst
1107  return true;
1108  }
1109 
1110  virtual BasePointer _getArg(size_t) const { // nArgNum-th variable, 0-based, const version
1111  return nullptr;
1112  }
1113 
1114  BasePointer _simp() const
1115  {
1116  BasePointer pRet;
1117  if (_depth(true) > CFUN_SIMPS_STACK_DEPTH) {
1118  pRet = this->_clone();
1119 #ifdef CFUN_DEBUG
1120  std::cout << "WARNING! Stack depth " << CFUN_SIMPS_STACK_DEPTH << " reached" << std::endl;
1121 #endif
1122  }
1123  else {
1124  pRet = this->_simpl();
1125  }
1126  _depth(false);
1127  return pRet;
1128  }
1130 };
1131 
1132 
1139 template <typename T>
1140 class UnaryFunction : public BaseFunction<T>
1141 {
1142 protected:
1145 
1147  virtual BasePointer _simpl() const = 0; // returns simplified function as a new object
1148  virtual int _depth(bool) const = 0; // call stack acquire and release
1150 
1151 public:
1158  : mf0()
1159  {
1160  }
1161 
1166  : mf0(rfSrc.mf0)
1167  {
1168  }
1169 
1174  : mf0(std::move(rfSrc.mf0))
1175  {
1176  }
1177 
1182  : mf0(pfSrc)
1183  {
1184  }
1185 
1187  : mf0(std::move(pfSrc))
1188  {
1189  }
1190 
1194  UnaryFunction(const std::string& sArg, const string_array& saVars,
1195  const string_array& saParameters, const string_array& saMeanings)
1196  : mf0(FunctionFactory<T>::compile(sArg, 0, sArg.length(), saVars, saParameters, saMeanings))
1197  {
1198  }
1199 
1203  UnaryFunction(const std::string& sArg, size_t nF, size_t nL, const string_array& saVars,
1204  const string_array& saParameters, const string_array& saMeanings)
1205  : mf0(FunctionFactory<T>::compile(sArg, nF, nL, saVars, saParameters, saMeanings))
1206  {
1207  }
1208 
1213  {
1214  mf0 = rfSrc.mf0;
1215  return *this;
1216  }
1217 
1222  {
1223  mf0 = std::move(rfSrc.mf0);
1224  return *this;
1225  }
1226 
1228  virtual int _kind() const = 0;
1229  virtual T _value(const T* pdVars) const = 0;
1230  virtual BasePointer _clone() const = 0;
1231  virtual BasePointer _deriv(size_t nVarNum) const = 0;
1232  virtual const char* _name() const = 0;
1233 
1234  bool _equals(const BasePointer& pfSrc) const override
1235  {
1236  return pfSrc &&
1237  mf0 &&
1238  this->_kind() == pfSrc->_kind() &&
1239  mf0->_equals(pfSrc->_getArg(0));
1240  }
1241 
1242  BasePointer _getArg(size_t nArgNum) const override
1243  {
1244  return nArgNum ? nullptr : mf0;
1245  }
1246 
1247  std::string _format(int nPrecision) const override
1248  {
1249  std::ostringstream osBuf;
1250  osBuf << this->_name() << CFUN_O_PARENTH << mf0->_format(nPrecision) << CFUN_C_PARENTH;
1251  return osBuf.str();
1252  }
1254 };
1255 
1256 
1263 template <typename T>
1265 {
1266 protected:
1269 
1271  void BinCtr(const std::string& sBodyCommaBody, // for bodies like pow(a,b) and sat(a,b)
1272  size_t nFirst, size_t nLast,
1273  const string_array& saVars,
1274  const string_array& saParameters, const string_array& saMeanings) throw(cvmexception)
1275  {
1276  std::string sLeft, sRight;
1277  if (__separate(sBodyCommaBody, nFirst, nLast, sLeft, sRight) == 1) {
1278  this->mf0 = FunctionFactory<T>::compile(sLeft, 0, sLeft.length(), saVars, saParameters, saMeanings);
1279  this->mf1 = FunctionFactory<T>::compile(sRight, 0, sRight.length(), saVars, saParameters, saMeanings);
1280  }
1281  else {
1282  throw cvmexception(CFUN_PARSEERROR, sBodyCommaBody.c_str(), __format_vars(saVars).c_str());
1283  }
1284  }
1285 
1286  virtual BasePointer _simpl() const = 0; // returns simplified function as a new object
1287  virtual int _depth(bool) const = 0; // call stack acquire and release
1289 
1290 public:
1295  : mf1()
1296  {
1297  }
1298 
1303  : UnaryFunction<T>(rfSrc.mf0),
1304  mf1(rfSrc.mf1)
1305  {
1306  }
1307 
1312  : UnaryFunction<T>(std::move(rfSrc.mf0)),
1313  mf1(std::move(rfSrc.mf1))
1314  {
1315  }
1316 
1320  BinaryFunction(const BaseFunction<T>& rfSrc0, const BaseFunction<T>& rfSrc1)
1321  : UnaryFunction<T>(rfSrc0),
1322  mf1(rfSrc1.mf1)
1323  {
1324  }
1325 
1329  BinaryFunction(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
1330  : UnaryFunction<T>(pfSrc0),
1331  mf1(pfSrc1)
1332  {
1333  }
1334 
1338  BinaryFunction(const std::string& sArg1, const std::string& sArg2,
1339  const string_array& saVars,
1340  const string_array& saParameters, const string_array& saMeanings)
1341  : UnaryFunction<T>(sArg1, 0, sArg1.length(), saVars, saParameters, saMeanings),
1342  mf1(FunctionFactory<T>::compile(sArg2, 0, sArg2.length(), saVars, saParameters, saMeanings))
1343  {
1344  }
1345 
1349  BinaryFunction(const std::string& sArgs,
1350  size_t nF1, size_t nL1, size_t nF2, size_t nL2,
1351  const string_array& saVars,
1352  const string_array& saParameters, const string_array& saMeanings)
1353  : UnaryFunction<T>(sArgs, nF1, nL1, saVars, saParameters, saMeanings),
1354  mf1(FunctionFactory<T>::compile(sArgs, nF2, nL2, saVars, saParameters, saMeanings))
1355  {
1356  }
1357 
1361  BinaryFunction(const std::string& sArg, size_t nFirst, size_t nLast,
1362  const string_array& saVars,
1363  const string_array& saParameters, const string_array& saMeanings)
1364  : mf1()
1365  {
1366  std::string sArg1, sArg2;
1367  if (__separate(sArg, nFirst, nLast, sArg1, sArg2) == 1) {
1368  this->mf0 = FunctionFactory<T>::compile(sArg1, 0, sArg1.length(), saVars, saParameters, saMeanings);
1369  this->mf1 = FunctionFactory<T>::compile(sArg2, 0, sArg2.length(), saVars, saParameters, saMeanings);
1370  }
1371  }
1372 
1377  {
1378  this->mf0 = rfSrc.mf0;
1379  this->mf1 = rfSrc.mf1;
1380  return *this;
1381  }
1382 
1387  {
1388  this->mf0 = std::move(rfSrc.mf0);
1389  this->mf1 = std::move(rfSrc.mf1);
1390  return *this;
1391  }
1392 
1394  virtual int _kind() const = 0;
1395  virtual T _value(const T* pdVars) const = 0;
1396  virtual BasePointer _clone() const = 0;
1397  virtual BasePointer _deriv(size_t nVarNum) const = 0;
1398  virtual std::string _format(int nPrecision) const = 0;
1399 
1400  bool _equals(const BasePointer& pfSrc) const override
1401  {
1402  return pfSrc && this->mf0 && this->mf1 &&
1403  this->_kind() == pfSrc->_kind() &&
1404  this->mf0->_equals(pfSrc->_getArg(0)) &&
1405  this->mf1->_equals(pfSrc->_getArg(1));
1406  }
1407 
1408  BasePointer _getArg(size_t nArgNum) const override
1409  {
1410  return nArgNum ? this->mf1 : this->mf0;
1411  }
1412 
1413  const char* _name() const override
1414  {
1415 #ifdef _DEBUG
1416  assert(false);
1417 #endif
1418  static const char sz_exp[] = ""; // no name for binaries
1419  return sz_exp;
1420  }
1422 };
1423 
1424 
1426 template <typename T>
1427 class Fconst : public BaseFunction<T>
1428 {
1429 private:
1430  T mdConst;
1431  bool mbValid;
1432 
1433  int _kind() const override {
1434  return CFUN_K_CONST;
1435  }
1436 
1437 protected:
1438  typedef typename BaseFunction<T>::BasePointer BasePointer;
1439 
1440  BasePointer _simpl() const override {
1441  return this->_clone();
1442  }
1443 
1444  int _depth(bool) const override {
1445  return 1;
1446  }
1447 
1448 public:
1449  Fconst()
1450  : mdConst(CFUN_M_ZERO),
1451  mbValid(true)
1452  {
1453  }
1454 
1455  Fconst(const Fconst& rfSrc)
1456  : BaseFunction<T>(),
1457  mdConst(rfSrc.mdConst),
1458  mbValid(rfSrc.mbValid)
1459  {
1460  }
1461 
1462  Fconst(const T& rdSrc)
1463  : mdConst(rdSrc),
1464  mbValid(true)
1465  {
1466  }
1467 
1468  Fconst(const std::string& sConst, bool bThrow = true)
1469  : mdConst(CFUN_M_ZERO),
1470  mbValid(Helper<T>::convert(sConst, mdConst, bThrow))
1471  {
1472  }
1473 
1474  bool is_valid() const override {
1475  return mbValid;
1476  }
1477 
1478  T _value(const T*) const override {
1479  return mdConst;
1480  }
1481 
1482  BasePointer _clone() const override {
1483  return std::make_shared<Fconst<T>>(*this);
1484  }
1485 
1486  BasePointer _deriv(size_t) const override {
1487  return std::make_shared<Fconst<T>>();
1488  }
1489 
1490  std::string _format(int nPrecision) const override {
1491  return Helper<T>::_format(mdConst, nPrecision);
1492  }
1493 
1494  bool _equals(const BasePointer& pfSrc) const override {
1495  return this->_kind() == pfSrc->_kind() && Comparator<T,T>::eq(mdConst, pfSrc->_value(nullptr));
1496  }
1497 
1498 protected:
1500  template<typename U>
1501  class Helper {
1502  public:
1503  static std::string _format(const U& v, int nPrecision)
1504  {
1505  std::ostringstream osBuf;
1506  if (nPrecision > 0) {
1507  osBuf.precision(nPrecision);
1508  osBuf.setf(std::ios::scientific | std::ios::showpoint | std::ios::left);
1509  }
1510  if (v < CFUN_M_ZERO) {
1511  osBuf << CFUN_O_PARENTH << v << CFUN_C_PARENTH;
1512  }
1513  else {
1514  osBuf << v;
1515  }
1516  return osBuf.str();
1517  }
1518  static bool convert(const std::string& s, U& u, bool bThrow) throw(cvmexception)
1519  {
1520  bool ret = __parse_num<U>(s, u);
1521  if (bThrow && !ret) {
1522  throw cvmexception(CFUN_PARSEERROR, s.c_str(), "n/a");
1523  }
1524  return ret;
1525  }
1526  };
1527 
1528  template<typename U>
1529  class Helper<std::complex<U> > {
1530  typedef std::complex<U> UC;
1531  public:
1532  static std::string _format(const UC& v, int nPrecision)
1533  {
1534  std::ostringstream osBuf;
1535  if (nPrecision > 0) {
1536  osBuf.precision(nPrecision);
1537  osBuf.setf(std::ios::scientific | std::ios::showpoint | std::ios::left);
1538  }
1539  osBuf << v;
1540  return osBuf.str();
1541  }
1542  static bool convert(const std::string& s, UC& uc, bool bThrow) throw(cvmexception)
1543  {
1544  bool ret1 = true, ret2 = true;
1545  std::string sRe, sIm;
1546  if (__separate(s, 0, s.length(), sRe, sIm) == 1) {
1547  U re, im;
1548  ret1 = __parse_num<U>(sRe, re);
1549  if (bThrow && !ret1) {
1550  throw cvmexception(CFUN_PARSEERROR, sRe.c_str(), "n/a");
1551  }
1552  ret2 = __parse_num<U>(sIm, im);
1553  if (bThrow && !ret2) {
1554  throw cvmexception(CFUN_PARSEERROR, sIm.c_str(), "n/a");
1555  }
1556  uc = UC(re, im);
1557  }
1558  else {
1559  U re;
1560  ret1 = __parse_num<U>(s, re);
1561  if (bThrow && !ret1) {
1562  throw cvmexception(CFUN_PARSEERROR, s.c_str(), "n/a");
1563  }
1564  uc = UC(re, CFUN_M_ZERO);
1565  }
1566  return ret1 && ret2;
1567  }
1568  };
1570 };
1571 
1572 template <typename T>
1573 class Finfinity : public BaseFunction<T>
1574 {
1575 private:
1576  int _kind() const override {
1577  return CFUN_K_INFINITY;
1578  }
1579 
1580 protected:
1581  typedef typename BaseFunction<T>::BasePointer BasePointer;
1582 
1583  BasePointer _simpl() const override {
1584  return this->_clone();
1585  }
1586 
1587  int _depth(bool) const override {
1588  return 1;
1589  }
1590 
1591 public:
1592  Finfinity()
1593  : BaseFunction<T>()
1594  {
1595  }
1596 
1597  T _value(const T*) const override {
1598  return basic_cvmMachMax<T>();
1599  }
1600 
1601  BasePointer _clone() const {
1602  return std::make_shared<Finfinity<T>>();
1603  }
1604 
1605  BasePointer _deriv(size_t) const override {
1606  return this->_clone();
1607  }
1608 
1609  std::string _format(int) const override {
1610  return CFUN_SINF;
1611  }
1612 
1613  bool _equals(const BasePointer& pfSrc) const override {
1614  return this->_kind() == pfSrc->_kind();
1615  }
1616 };
1617 
1618 template <typename T>
1619 class Fmninfinity : public BaseFunction<T>
1620 {
1621 private:
1622  int _kind() const override {
1623  return CFUN_K_MNINFINITY;
1624  }
1625 
1626 protected:
1627  typedef typename BaseFunction<T>::BasePointer BasePointer;
1628 
1629  BasePointer _simpl() const override {
1630  return this->_clone();
1631  }
1632 
1633  int _depth(bool) const override {
1634  return 1;
1635  }
1636 
1637 public:
1638  Fmninfinity()
1639  : BaseFunction<T>()
1640  {
1641  }
1642 
1643  T _value(const T*) const override {
1644  return -basic_cvmMachMax<T>();
1645  }
1646 
1647  BasePointer _clone() const override {
1648  return std::make_shared<Fmninfinity<T>>();
1649  }
1650 
1651  BasePointer _deriv(size_t) const override {
1652  return this->_clone();
1653  }
1654 
1655  std::string _format(int) const override {
1656  return CFUN_SMINF;
1657  }
1658 
1659  bool _equals(const BasePointer& pfSrc) const override {
1660  return this->_kind() == pfSrc->_kind();
1661  }
1662 };
1663 
1664 template <typename T>
1665 class Fplus : public BinaryFunction<T>
1666 {
1667 private:
1668  int _kind() const override {
1669  return CFUN_K_PLUS;
1670  }
1671 
1672 protected:
1673  int _depth(bool bAcquire) const override
1674  {
1675  static int nDepth;
1676  return bAcquire ? ++nDepth : --nDepth;
1677  }
1678 
1679  typedef typename BinaryFunction<T>::BasePointer BasePointer;
1680  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
1681 
1682  BasePointer _simpl() const override
1683  {
1684  int i, j, k;
1685  BasePointer fZero = std::make_shared<Fconst<T>>();
1686  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
1687 
1688  for (i = 0; i <= 1; ++i)
1689  {
1690  if (fCopy[i]->_equals(fZero))
1691  { // 0 + f(x) = f(x) | f(x) + 0 = f(x)
1692  return fCopy[__not(i)];
1693  }
1694  }
1695  for (i = 0; i <= 1; ++i)
1696  {
1697  if (fCopy[i]->_kind() == CFUN_K_INFINITY)
1698  { // inf + f(x) = inf | f(x) + inf = inf
1699  return std::make_shared<Finfinity<T>>();
1700  }
1701  }
1702  for (i = 0; i <= 1; ++i)
1703  {
1704  if (fCopy[i]->_kind() == CFUN_K_MNINFINITY)
1705  { // -inf + f(x) = -inf | f(x) + -inf = -inf
1706  return std::make_shared<Fmninfinity<T>>();
1707  }
1708  }
1709  if (fCopy[0]->_kind() == CFUN_K_CONST &&
1710  fCopy[1]->_kind() == CFUN_K_CONST)
1711  { // 1 + 2 = 3
1712  return std::make_shared<Fconst<T>>(fCopy[0]->_value(nullptr) + fCopy[1]->_value(nullptr));
1713  }
1714  for (i = 0; i <= 1; ++i)
1715  {
1716  if (fCopy[i]->_kind() == CFUN_K_CONST)
1717  { // x + (-1) = x-1
1718  T val = fCopy[i]->_value(nullptr);
1719  if (Comparator<T,T>::lt(val, CFUN_M_ZERO))
1720  {
1721  return std::make_shared<Fminus<T>>(fCopy[__not(i)], std::make_shared<Fconst<T>>(-val))->_simp();
1722  }
1723  }
1724  }
1725  if (fCopy[0]->_equals(fCopy[1]))
1726  { // x+x = 2*x
1727  return std::make_shared<Fmult<T>>(std::make_shared<Fconst<T>>(CFUN_M_TWO), fCopy[0])->_simp();
1728  }
1729 
1730  for (i = 0; i <= 1; ++i)
1731  {
1732  if (fCopy[i]->_kind() == CFUN_K_UMINUS)
1733  { // -a + b = b - a a + -b = a - b
1734  return std::make_shared<Fminus<T>>(fCopy[__not(i)], fCopy[i]->_getArg(0))->_simp();
1735  }
1736  }
1737 
1738  if (fCopy[0]->_kind() == CFUN_K_MULT &&
1739  fCopy[1]->_kind() == CFUN_K_MULT)
1740  {
1741  for (i = 0; i <= 1; ++i)
1742  { // C*A+C*B = C*(A+B)
1743  for (j = 0; j <= 1; ++j)
1744  { // C*A+B*C = C*(A+B)
1745  if (fCopy[0]->_getArg(i)->_equals(fCopy[1]->_getArg(j)))
1746  { // A*C+C*B = C*(A+B)
1747  return
1748  std::make_shared<Fmult<T>>(fCopy[0]->_getArg(i), // A*C+B*C = C*(A+B)
1749  std::make_shared<Fplus<T>>(fCopy[0]->_getArg(__not(i)),
1750  fCopy[1]->_getArg(__not(j))))->_simp();
1751  }
1752  }
1753  }
1754  }
1755  for (j = 0; j <= 1; ++j)
1756  {
1757  if (fCopy[j]->_kind() == CFUN_K_MULT)
1758  { // a*x + x = (a+1)*x
1759  for (i = 0; i <= 1; ++i)
1760  {
1761  if (fCopy[j]->_getArg(i)->_equals(fCopy[__not(j)]))
1762  {
1763  return
1764  std::make_shared<Fmult<T>>(fCopy[__not(j)],
1765  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(__not(i)),
1766  std::make_shared<Fconst<T>>(CFUN_M_ONE)))->_simp();
1767  }
1768  }
1769  }
1770  }
1771  if (fCopy[0]->_kind() == CFUN_K_DIV &&
1772  fCopy[1]->_kind() == CFUN_K_DIV && // x/a+y/a = (x+y)/a
1773  fCopy[0]->_getArg(1)->_equals(fCopy[1]->_getArg(1)))
1774  {
1775  return
1776  std::make_shared<Fdiv<T>>(std::make_shared<Fplus<T>>(fCopy[0]->_getArg(0),
1777  fCopy[1]->_getArg(0)),
1778  fCopy[0]->_getArg(1))->_simp();
1779  }
1780  for (j = 0; j <= 1; ++j)
1781  {
1782  if (fCopy[j]->_kind() == CFUN_K_PLUS)
1783  { // x+a + a
1784  for (i = 0; i <= 1; ++i)
1785  {
1786  BasePointer fTmp =
1787  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(i),
1788  fCopy[__not(j)]);
1789  BasePointer fTmps(fTmp->_simp());
1790  if (!fTmp->_equals(fTmps))
1791  {
1792  return
1793  std::make_shared<Fplus<T>>(fTmps,
1794  fCopy[j]->_getArg(__not(i)))->_simp();
1795  }
1796  }
1797  if (fCopy[__not(j)]->_kind() == CFUN_K_PLUS)
1798  { // x+a + x+b
1799  for (i = 0; i <= 1; ++i)
1800  {
1801  for (k = 0; k <= 1; ++k)
1802  {
1803  BasePointer fTmp =
1804  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(i),
1805  fCopy[__not(j)]->_getArg(k));
1806  BasePointer fTmps(fTmp->_simp());
1807  if (!fTmp->_equals(fTmps))
1808  {
1809  return
1810  std::make_shared<Fplus<T>>(fTmps,
1811  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(__not(i)),
1812  fCopy[__not(j)]->_getArg(__not(k))))->_simp();
1813  }
1814  }
1815  }
1816  }
1817  if (fCopy[__not(j)]->_kind() == CFUN_K_MINUS)
1818  { // x+a + x-b | x-a + x+b
1819  for (i = 0; i <= 1; ++i)
1820  {
1821  BasePointer fTmp =
1822  std::make_shared<Fminus<T>>(fCopy[j]->_getArg(i),
1823  fCopy[__not(j)]->_getArg(1));
1824  BasePointer fTmps(fTmp->_simp());
1825  if (!fTmp->_equals(fTmps))
1826  {
1827  return
1828  std::make_shared<Fplus<T>>(fTmps,
1829  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(__not(i)),
1830  fCopy[__not(j)]->_getArg(0)))->_simp();
1831  }
1832  }
1833  for (i = 0; i <= 1; ++i)
1834  {
1835  BasePointer fTmp =
1836  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(i),
1837  fCopy[__not(j)]->_getArg(0));
1838  BasePointer fTmps(fTmp->_simp());
1839  if (!fTmp->_equals(fTmps))
1840  {
1841  return
1842  std::make_shared<Fplus<T>>(fTmps,
1843  std::make_shared<Fminus<T>>(fCopy[j]->_getArg(__not(i)),
1844  fCopy[__not(j)]->_getArg(1)))->_simp();
1845  }
1846  }
1847  }
1848  }
1849  if (fCopy[j]->_kind() == CFUN_K_MINUS)
1850  {
1851  { // a-x + a
1852  BasePointer fTmp =
1853  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(0),
1854  fCopy[__not(j)]);
1855  BasePointer fTmps(fTmp->_simp());
1856  if (!fTmp->_equals(fTmps))
1857  {
1858  return
1859  std::make_shared<Fminus<T>>(fTmps,
1860  fCopy[j]->_getArg(1))->_simp();
1861  }
1862  }
1863  {
1864  BasePointer fTmp =
1865  std::make_shared<Fminus<T>>(fCopy[__not(j)], // x-a + a
1866  fCopy[j]->_getArg(1));
1867  BasePointer fTmps(fTmp->_simp());
1868  if (!fTmp->_equals(fTmps))
1869  {
1870  return
1871  std::make_shared<Fplus<T>>(fTmps,
1872  fCopy[j]->_getArg(0))->_simp();
1873  }
1874  }
1875 
1876  if (fCopy[__not(j)]->_kind() == CFUN_K_MINUS)
1877  { // x-a + x-b
1878  for (i = 0; i <= 1; ++i)
1879  {
1880  BasePointer fTmp =
1881  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(i),
1882  fCopy[__not(j)]->_getArg(i));
1883  BasePointer fTmps(fTmp->_simp());
1884  if (!fTmp->_equals(fTmps))
1885  {
1886  BasePointer fTmp =
1887  i ?
1888  std::make_shared<Fminus<T>>(std::make_shared<Fplus<T>>(fCopy[j]->_getArg(0),
1889  fCopy[__not(j)]->_getArg(0)),
1890  fTmps)
1891  :
1892  std::make_shared<Fminus<T>>(fTmps,
1893  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(1),
1894  fCopy[__not(j)]->_getArg(1)));
1895  return fTmp->_simp();
1896  }
1897  }
1898  BasePointer fTmp =
1899  std::make_shared<Fminus<T>>(fCopy[j]->_getArg(0), // x-a + b-x
1900  fCopy[__not(j)]->_getArg(1));
1901  BasePointer fTmps(fTmp->_simp());
1902  if (!fTmp->_equals(fTmps))
1903  {
1904  return
1905  std::make_shared<Fplus<T>>(std::make_shared<Fminus<T>>(fCopy[__not(j)]->_getArg(0),
1906  fCopy[j]->_getArg(1)),
1907  fTmps)->_simp();
1908  }
1909  }
1910  }
1911  }
1912  return std::make_shared<Fplus<T>>(fCopy[0], fCopy[1]);
1913  }
1914 
1915 public:
1916  Fplus(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
1917  : BinaryFunction<T>(pfSrc0, pfSrc1)
1918  {
1919  }
1920 
1921  Fplus(const std::string& sAddend1, const std::string& sAddend2,
1922  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
1923  : BinaryFunction<T>(sAddend1, sAddend2, saVars, saParameters, saMeanings)
1924  {
1925  }
1926 
1927  Fplus(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
1928  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
1929  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
1930  {
1931  }
1932 
1933  T _value(const T* pdVars) const override {
1934  return this->mf0->_value(pdVars) + this->mf1->_value(pdVars);
1935  }
1936 
1937  BasePointer _clone() const override {
1938  return std::make_shared<Fplus<T>>(this->mf0, this->mf1);
1939  }
1940 
1941  BasePointer _deriv(size_t nVarNum) const override
1942  {
1943  return
1944  std::make_shared<Fplus<T>>(this->mf0->_deriv(nVarNum),
1945  this->mf1->_deriv(nVarNum))->_simp();
1946  }
1947 
1948  std::string _format(int nPrecision) const override
1949  {
1950  std::ostringstream osBuf;
1951  osBuf << this->mf0->_format(nPrecision) << CFUN_SPLUS;
1952  if (this->mf1->_kind() == CFUN_K_UMINUS) {
1953  osBuf << CFUN_O_PARENTH << this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
1954  }
1955  else {
1956  osBuf << this->mf1->_format(nPrecision);
1957  }
1958  return osBuf.str();
1959  }
1960 };
1961 
1962 template <typename T>
1963 class Fminus : public BinaryFunction<T>
1964 {
1965 private:
1966  int _kind() const override {
1967  return CFUN_K_MINUS;
1968  }
1969 
1970 protected:
1971  int _depth(bool bAcquire) const override
1972  {
1973  static int nDepth;
1974  return bAcquire ? ++nDepth : --nDepth;
1975  }
1976 
1977  typedef typename BinaryFunction<T>::BasePointer BasePointer;
1978  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
1979 
1980  BasePointer _simpl() const override
1981  {
1982  int i, j, k;
1983  BasePointer fZero = std::make_shared<Fconst<T>>();
1984  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
1985  if (fCopy[0]->_equals(fZero))
1986  { // 0 - x = -x
1987  return std::make_shared<Fuminus<T>>(fCopy[1])->_simp();
1988  }
1989  if (fCopy[1]->_equals(fZero)) // x - 0 = x
1990  {
1991  return fCopy[0];
1992  }
1993  if (fCopy[0]->_kind() == CFUN_K_INFINITY) // inf - x = inf
1994  {
1995  return std::make_shared<Finfinity<T>>();
1996  }
1997  if (fCopy[1]->_kind() == CFUN_K_MNINFINITY) // x - -inf = inf
1998  {
1999  return std::make_shared<Finfinity<T>>();
2000  }
2001  if (fCopy[0]->_kind() == CFUN_K_MNINFINITY) // -inf - x = -inf
2002  {
2003  return std::make_shared<Fmninfinity<T>>();
2004  }
2005  if (fCopy[1]->_kind() == CFUN_K_INFINITY) // x - inf = -inf
2006  {
2007  return std::make_shared<Fmninfinity<T>>();
2008  }
2009  if (fCopy[0]->_kind() == CFUN_K_CONST &&
2010  fCopy[1]->_kind() == CFUN_K_CONST) // 3 - 2 = 1
2011  {
2012  return std::make_shared<Fconst<T>>(fCopy[0]->_value(nullptr)-
2013  fCopy[1]->_value(nullptr));
2014  }
2015  if (fCopy[0]->_equals(fCopy[1])) // x - x = 0
2016  {
2017  return std::make_shared<Fconst<T>>();
2018  }
2019  if (fCopy[0]->_kind() == CFUN_K_UMINUS) // -a - b = -(a + b)
2020  {
2021  return
2022  std::make_shared<Fuminus<T>>(std::make_shared<Fplus<T>>(fCopy[0]->_getArg(0),
2023  fCopy[1])->_simp())->_simp();
2024  }
2025  if (fCopy[1]->_kind() == CFUN_K_UMINUS) // a - -b = a + b
2026  {
2027  return
2028  std::make_shared<Fplus<T>>(fCopy[0],
2029  fCopy[1]->_getArg(0))->_simp();
2030  }
2031  if (fCopy[0]->_kind() == CFUN_K_MULT &&
2032  fCopy[1]->_kind() == CFUN_K_MULT)
2033  {
2034  for (i = 0; i <= 1; ++i) // C*A-C*B = C*(A-B)
2035  {
2036  for (j = 0; j <= 1; ++j) // C*A-B*C = C*(A-B)
2037  {
2038  if (fCopy[0]->_getArg(i)->_equals(fCopy[1]->_getArg(j))) // A*C-C*B = C*(A-B)
2039  {
2040  return
2041  std::make_shared<Fmult<T>>(fCopy[0]->_getArg(i), // A*C-B*C = C*(A-B)
2042  std::make_shared<Fminus<T>>(fCopy[0]->_getArg(__not(i)),
2043  fCopy[1]->_getArg(__not(j))))->_simp();
2044  }
2045  }
2046  }
2047  }
2048  for (j = 0; j <= 1; ++j)
2049  {
2050  if (fCopy[j]->_kind() == CFUN_K_MULT)
2051  { // a*x - x = (a-1)*x
2052  for (i = 0; i <= 1; ++i)
2053  {
2054  if (fCopy[j]->_getArg(i)->_equals(fCopy[__not(j)]))
2055  {
2056  BasePointer fTmp =
2057  std::make_shared<Fmult<T>>(fCopy[__not(j)],
2058  j ?
2059  std::make_shared<Fminus<T>>(std::make_shared<Fconst<T>>(CFUN_M_ONE),
2060  fCopy[j]->_getArg(__not(i)))
2061  :
2062  std::make_shared<Fminus<T>>(fCopy[j]->_getArg(__not(i)),
2063  std::make_shared<Fconst<T>>(CFUN_M_ONE)));
2064  return fTmp->_simp();
2065  }
2066  }
2067  }
2068  }
2069  if (fCopy[0]->_kind() == CFUN_K_DIV &&
2070  fCopy[1]->_kind() == CFUN_K_DIV && // x/a-y/a = (x+y)/a
2071  fCopy[0]->_getArg(1)->_equals(fCopy[1]->_getArg(1)))
2072  {
2073  return
2074  std::make_shared<Fdiv<T>>(std::make_shared<Fminus<T>>(fCopy[0]->_getArg(0),
2075  fCopy[1]->_getArg(0)),
2076  fCopy[0]->_getArg(1))->_simp();
2077  }
2078  for (j = 0; j <= 1; ++j)
2079  {
2080  if (fCopy[j]->_kind() == CFUN_K_PLUS) // [x+a] - a | a - [x+a]
2081  {
2082  for (i = 0; i <= 1; ++i)
2083  {
2084  BasePointer fTmp = std::make_shared<Fminus<T>>(fCopy[j]->_getArg(i),
2085  fCopy[__not(j)]);
2086  BasePointer fTmps(fTmp->_simp());
2087  if (!fTmp->_equals(fTmps))
2088  {
2089  if (j)
2090  {
2091  return
2092  std::make_shared<Fminus<T>>(fTmps,
2093  fCopy[j]->_getArg(__not(i)))->_simp();
2094  }
2095  else {
2096  return
2097  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(__not(i)),
2098  fTmps)->_simp();
2099  }
2100  }
2101  }
2102  if (fCopy[__not(j)]->_kind() == CFUN_K_PLUS) // x+a - x+b
2103  {
2104  for (i = 0; i <= 1; ++i)
2105  {
2106  for (k = 0; k <= 1; ++k)
2107  {
2108  BasePointer fTmp = std::make_shared<Fminus<T>>(fCopy[j]->_getArg(i),
2109  fCopy[__not(j)]->_getArg(k));
2110  BasePointer fTmps(fTmp->_simp());
2111  if (!fTmp->_equals(fTmps))
2112  {
2113  return
2114  std::make_shared<Fminus<T>>(fTmps,
2115  std::make_shared<Fplus<T>>(fCopy[j]->_getArg(__not(i)),
2116  fCopy[__not(j)]->_getArg(__not(k))))->_simp();
2117  }
2118  }
2119  }
2120  }
2121  if (fCopy[__not(j)]->_kind() == CFUN_K_MINUS) // x+a - x-b | x-a - x+b
2122  {
2123  if (!j)
2124  {
2125  return
2126  std::make_shared<Fplus<T>>(fCopy[0],
2127  std::make_shared<Fminus<T>>(fCopy[1]->_getArg(1),
2128  fCopy[1]->_getArg(0)))->_simp();
2129  }
2130  else // j==1, i.e. x-a - x+b
2131  {
2132  for (i = 0; i <= 1; ++i)
2133  {
2134  BasePointer fTmp = std::make_shared<Fminus<T>>(fCopy[0]->_getArg(0),
2135  fCopy[1]->_getArg(i));
2136  BasePointer fTmps(fTmp->_simp());
2137  if (!fTmp->_equals(fTmps))
2138  {
2139  return
2140  std::make_shared<Fminus<T>>(fTmps,
2141  std::make_shared<Fplus<T>>(fCopy[0]->_getArg(1),
2142  fCopy[1]->_getArg(__not(i))))->_simp();
2143  }
2144  }
2145  for (i = 0; i <= 1; ++i) // a-x - x+b
2146  {
2147  BasePointer fTmp = std::make_shared<Fplus<T>>(fCopy[0]->_getArg(1),
2148  fCopy[1]->_getArg(i));
2149  BasePointer fTmps(fTmp->_simp());
2150  if (!fTmp->_equals(fTmps))
2151  {
2152  return
2153  std::make_shared<Fminus<T>>(std::make_shared<Fminus<T>>(fCopy[0]->_getArg(0),
2154  fCopy[1]->_getArg(__not(i))),
2155  fTmps)->_simp();
2156  }
2157  }
2158  }
2159  }
2160  }
2161  if (fCopy[j]->_kind() == CFUN_K_MINUS) // a-x - a | a - a-x
2162  {
2163  if (j) // a - a-x == a + x-a
2164  {
2165  return
2166  std::make_shared<Fplus<T>>(fCopy[0],
2167  std::make_shared<Fminus<T>>(fCopy[1]->_getArg(1),
2168  fCopy[1]->_getArg(0)))->_simp();
2169  }
2170  else
2171  {
2172  { // j==0 i.e. a-x - a
2173  BasePointer fTmp = std::make_shared<Fminus<T>>(fCopy[j]->_getArg(0),
2174  fCopy[__not(j)]);
2175  BasePointer fTmps(fTmp->_simp());
2176  if (!fTmp->_equals(fTmps))
2177  {
2178  return
2179  std::make_shared<Fminus<T>>(fTmps,
2180  fCopy[j]->_getArg(1))->_simp();
2181  }
2182  }
2183 
2184  { // x-a - a
2185  BasePointer fTmp = std::make_shared<Fplus<T>>(fCopy[j]->_getArg(1),
2186  fCopy[__not(j)]);
2187  BasePointer fTmps(fTmp->_simp());
2188  if (!fTmp->_equals(fTmps))
2189  {
2190  return
2191  std::make_shared<Fminus<T>>(fCopy[j]->_getArg(0),
2192  fTmps)->_simp();
2193  }
2194  }
2195  }
2196  }
2197  }
2198  return std::make_shared<Fminus<T>>(fCopy[0], fCopy[1]);
2199  }
2200 
2201 public:
2202  Fminus(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
2203  : BinaryFunction<T>(pfSrc0, pfSrc1)
2204  {
2205  }
2206 
2207  Fminus(const std::string& sMinuend, const std::string& sSubtrahend,
2208  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2209  : BinaryFunction<T>(sMinuend, sSubtrahend, saVars, saParameters, saMeanings)
2210  {
2211  }
2212 
2213  Fminus(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
2214  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2215  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
2216  {
2217  }
2218 
2219  T _value(const T* pdVars) const override {
2220  return this->mf0->_value(pdVars) - this->mf1->_value(pdVars);
2221  }
2222 
2223  BasePointer _clone() const override {
2224  return std::make_shared<Fminus<T>>(this->mf0, this->mf1);
2225  }
2226 
2227  BasePointer _deriv(size_t nVarNum) const override
2228  {
2229  return
2230  std::make_shared<Fminus<T>>(this->mf0->_deriv(nVarNum),
2231  this->mf1->_deriv(nVarNum))->_simp();
2232  }
2233 
2234  std::string _format(int nPrecision) const override
2235  {
2236  std::ostringstream osBuf;
2237  osBuf << this->mf0->_format(nPrecision) << CFUN_SMINUS;
2238  if (this->mf1->_kind() == CFUN_K_UMINUS) {
2239  osBuf << CFUN_O_PARENTH << this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
2240  }
2241  else {
2242  osBuf << this->mf1->_format(nPrecision);
2243  }
2244  return osBuf.str();
2245  }
2246 };
2247 
2248 template <typename T>
2249 class Fmult : public BinaryFunction<T>
2250 {
2251 private:
2252  int _kind() const override {
2253  return CFUN_K_MULT;
2254  }
2255 
2256 protected:
2257  int _depth(bool bAcquire) const override
2258  {
2259  static int nDepth;
2260  return bAcquire ? ++nDepth : --nDepth;
2261  }
2262 
2263  typedef typename BinaryFunction<T>::BasePointer BasePointer;
2264  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
2265 
2266  BasePointer _simpl() const override
2267  {
2268  int i, j, k;
2269  BasePointer fZero = std::make_shared<Fconst<T>>();
2270  BasePointer fOne = std::make_shared<Fconst<T>>(CFUN_M_ONE);
2271  BasePointer fMOne = std::make_shared<Fconst<T>>(CFUN_M_MONE);
2272  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
2273  for (i = 0; i <= 1; ++i)
2274  {
2275  if (fCopy[i]->_kind() == CFUN_K_INFINITY)
2276  {
2277  return std::make_shared<Finfinity<T>>();
2278  }
2279  if (fCopy[i]->_kind() == CFUN_K_MNINFINITY)
2280  {
2281  return std::make_shared<Fmninfinity<T>>();
2282  }
2283  }
2284  if (fCopy[0]->_equals(fZero) ||
2285  fCopy[1]->_equals(fZero)) // 0 * x = 0 | x * 0 = 0
2286  {
2287  return fZero;
2288  }
2289  for (i = 0; i <= 1; ++i)
2290  {
2291  if (fCopy[i]->_equals(fOne)) { // 1 * x = x
2292  return fCopy[__not(i)];
2293  }
2294  }
2295  for (i = 0; i <= 1; ++i)
2296  {
2297  if (fCopy[i]->_equals(fMOne)) // -1 * x = -x
2298  {
2299  return
2300  std::make_shared<Fuminus<T>>(fCopy[__not(i)])->_simp();
2301  }
2302  }
2303  if (fCopy[0]->_kind() == CFUN_K_CONST &&
2304  fCopy[1]->_kind() == CFUN_K_CONST) // 3 * 2 = 6
2305  {
2306  return std::make_shared<Fconst<T>>(fCopy[0]->_value(nullptr) * fCopy[1]->_value(nullptr));
2307  }
2308  if (fCopy[0]->_equals(fCopy[1])) // x * x = x^2
2309  {
2310  return
2311  std::make_shared<Fpower<T>>(fCopy[0],
2312  std::make_shared<Fconst<T>>(CFUN_M_TWO))->_simp();
2313  }
2314  if (fCopy[0]->_kind() == CFUN_K_UMINUS &&
2315  fCopy[1]->_kind() == CFUN_K_UMINUS) // (-a)*(-b) = a*b)
2316  {
2317  return
2318  std::make_shared<Fmult<T>>(fCopy[0]->_getArg(0),
2319  fCopy[1]->_getArg(0))->_simp();
2320  }
2321  for (i = 0; i <= 1; ++i)
2322  {
2323  if (fCopy[i]->_kind() == CFUN_K_UMINUS) // (-a)*b = -a*b
2324  {
2325  return
2326  std::make_shared<Fuminus<T>>(std::make_shared<Fmult<T>>(fCopy[i]->_getArg(0),
2327  fCopy[__not(i)]))->_simp();
2328  }
2329  }
2330  if (fCopy[0]->_kind() == CFUN_K_POWER && // x^a*x^b=x^(a+b)
2331  fCopy[1]->_kind() == CFUN_K_POWER &&
2332  fCopy[0]->_getArg(0)->_equals(fCopy[1]->_getArg(0)))
2333  {
2334  return
2335  std::make_shared<Fpower<T>>(fCopy[0]->_getArg(0),
2336  std::make_shared<Fplus<T>>(fCopy[0]->_getArg(1),
2337  fCopy[1]->_getArg(1)))->_simp();
2338  }
2339  if (fCopy[0]->_kind() == CFUN_K_EXP && // exp(a)*exp(b)=exp(a+b)
2340  fCopy[1]->_kind() == CFUN_K_EXP)
2341  {
2342  return
2343  std::make_shared<Fexp<T>>(std::make_shared<Fplus<T>>(fCopy[0]->_getArg(0),
2344  fCopy[1]->_getArg(0)))->_simp();
2345  }
2346  if (fCopy[0]->_kind() == CFUN_K_POWER && // x^a*x=x^(a+1)
2347  fCopy[0]->_getArg(0)->_equals(fCopy[1]))
2348  {
2349  return
2350  std::make_shared<Fpower<T>>(fCopy[1],
2351  std::make_shared<Fplus<T>>(fCopy[0]->_getArg(1),
2352  std::make_shared<Fconst<T>>(CFUN_M_ONE)))->_simp();
2353  }
2354  if (fCopy[1]->_kind() == CFUN_K_POWER && // x*x^a=x^(a+1)
2355  fCopy[1]->_getArg(0)->_equals(fCopy[0]))
2356  {
2357  return
2358  std::make_shared<Fpower<T>>(fCopy[0],
2359  std::make_shared<Fplus<T>>(fCopy[1]->_getArg(1),
2360  fOne))->_simp();
2361  }
2362 
2363  for (j = 0; j <= 1; ++j)
2364  {
2365  if (fCopy[j]->_kind() == CFUN_K_MULT) // x*a * a
2366  {
2367  for (i = 0; i <= 1; ++i)
2368  {
2369  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(i),
2370  fCopy[__not(j)]);
2371  BasePointer fTmps(fTmp->_simp());
2372  if (!fTmp->_equals(fTmps))
2373  {
2374  return
2375  std::make_shared<Fmult<T>>(fTmps,
2376  fCopy[j]->_getArg(__not(i)))->_simp();
2377  }
2378  }
2379  if (fCopy[__not(j)]->_kind() == CFUN_K_MULT) // x*a * x*b
2380  {
2381  for (i = 0; i <= 1; ++i)
2382  {
2383  for (k = 0; k <= 1; ++k)
2384  {
2385  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(i),
2386  fCopy[__not(j)]->_getArg(k));
2387  BasePointer fTmps(fTmp->_simp());
2388  if (!fTmp->_equals(fTmps))
2389  {
2390  return
2391  std::make_shared<Fmult<T>>(fTmps,
2392  std::make_shared<Fmult<T>>(fCopy[j]->_getArg(__not(i)),
2393  fCopy[__not(j)]->_getArg(__not(k))))->_simp();
2394  }
2395  }
2396  }
2397  }
2398  if (fCopy[__not(j)]->_kind() == CFUN_K_DIV) // x*a * x/b | x/a * x*b
2399  {
2400 
2401  for (i = 0; i <= 1; ++i)
2402  {
2403  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(i),
2404  fCopy[__not(j)]->_getArg(1));
2405  BasePointer fTmps(fTmp->_simp());
2406  if (!fTmp->_equals(fTmps))
2407  {
2408  return
2409  std::make_shared<Fmult<T>>(fTmps,
2410  std::make_shared<Fmult<T>>(fCopy[j]->_getArg(__not(i)),
2411  fCopy[__not(j)]->_getArg(0)))->_simp();
2412  }
2413  }
2414  for (i = 0; i <= 1; ++i)
2415  {
2416  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(i),
2417  fCopy[__not(j)]->_getArg(0));
2418  BasePointer fTmps(fTmp->_simp());
2419  if (!fTmp->_equals(fTmps))
2420  {
2421  return
2422  std::make_shared<Fmult<T>>(fTmps,
2423  std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(__not(i)),
2424  fCopy[__not(j)]->_getArg(1)))->_simp();
2425  }
2426  }
2427  }
2428  }
2429  if (fCopy[j]->_kind() == CFUN_K_DIV) // a/x * a
2430  {
2431  {
2432  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(0),
2433  fCopy[__not(j)]);
2434  BasePointer fTmps(fTmp->_simp());
2435  if (!fTmp->_equals(fTmps))
2436  {
2437  return
2438  std::make_shared<Fdiv<T>>(fTmps,
2439  fCopy[j]->_getArg(1))->_simp();
2440  }
2441  }
2442  { // x/a * a
2443  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[__not(j)],
2444  fCopy[j]->_getArg(1));
2445  BasePointer fTmps(fTmp->_simp());
2446  if (!fTmp->_equals(fTmps))
2447  {
2448  return
2449  std::make_shared<Fmult<T>>(fTmps,
2450  fCopy[j]->_getArg(0))->_simp();
2451  }
2452  }
2453 
2454  if (fCopy[__not(j)]->_kind() == CFUN_K_DIV) // x/a * x/b
2455  {
2456  for (i = 0; i <= 1; ++i)
2457  {
2458  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(i),
2459  fCopy[__not(j)]->_getArg(i));
2460  BasePointer fTmps(fTmp->_simp());
2461  if (!fTmp->_equals(fTmps))
2462  {
2463  BasePointer fTmp =
2464  i ?
2465  std::make_shared<Fdiv<T>>(std::make_shared<Fmult<T>>(fCopy[j]->_getArg(0),
2466  fCopy[__not(j)]->_getArg(0)),
2467  fTmps)
2468  :
2469  std::make_shared<Fdiv<T>>(fTmps,
2470  std::make_shared<Fmult<T>>(fCopy[j]->_getArg(1),
2471  fCopy[__not(j)]->_getArg(1)));
2472  return fTmp->_simp();
2473  }
2474  } // x/a * b/x
2475  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(0),
2476  fCopy[__not(j)]->_getArg(1));
2477  BasePointer fTmps(fTmp->_simp());
2478  if (!fTmp->_equals(fTmps))
2479  {
2480  return
2481  std::make_shared<Fmult<T>>(std::make_shared<Fdiv<T>>(fCopy[__not(j)]->_getArg(0),
2482  fCopy[j]->_getArg(1)),
2483  fTmps)->_simp();
2484  }
2485  }
2486  }
2487  }
2488  return std::make_shared<Fmult<T>>(fCopy[0], fCopy[1]);
2489  }
2490 
2491 public:
2492  Fmult(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
2493  : BinaryFunction<T>(pfSrc0, pfSrc1)
2494  {
2495  }
2496 
2497  Fmult(const std::string& sMultiplicand, const std::string& sMultiplier,
2498  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2499  : BinaryFunction<T>(sMultiplicand, sMultiplier, saVars, saParameters, saMeanings)
2500  {
2501  }
2502 
2503  Fmult(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
2504  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2505  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
2506  {
2507  }
2508 
2509  T _value(const T* pdVars) const override {
2510  return this->mf0->_value(pdVars) * this->mf1->_value(pdVars);
2511  }
2512 
2513  BasePointer _clone() const override {
2514  return std::make_shared<Fmult<T>>(this->mf0, this->mf1);
2515  }
2516 
2517  BasePointer _deriv(size_t nVarNum) const override
2518  {
2519  return
2520  std::make_shared<Fplus<T>>(std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
2521  this->mf1),
2522  std::make_shared<Fmult<T>>(this->mf0,
2523  this->mf1->_deriv(nVarNum)))->_simp();
2524  }
2525 
2526  std::string _format(int nPrecision) const override
2527  {
2528  std::ostringstream osBuf;
2529  switch (this->mf0->_kind()) {
2530  case CFUN_K_PLUS:
2531  case CFUN_K_MINUS:
2532  osBuf << CFUN_O_SPARENTH << this->mf0->_format(nPrecision) << CFUN_C_PARENTH << CFUN_SMULT;
2533  break;
2534  default:
2535  osBuf << this->mf0->_format(nPrecision) << CFUN_SMULT;
2536  break;
2537  }
2538  switch (this->mf1->_kind()) {
2539  case CFUN_K_PLUS:
2540  case CFUN_K_MINUS:
2541  case CFUN_K_UMINUS:
2542  osBuf << CFUN_O_SPARENTH << this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
2543  break;
2544  default:
2545  osBuf << this->mf1->_format(nPrecision);
2546  break;
2547  }
2548  return osBuf.str();
2549  }
2550 };
2551 
2552 template <typename T>
2553 class Fdiv : public BinaryFunction<T>
2554 {
2555 private:
2556  int _kind() const override {
2557  return CFUN_K_DIV;
2558  }
2559 
2560 protected:
2561  int _depth(bool bAcquire) const override
2562  {
2563  static int nDepth;
2564  return bAcquire ? ++nDepth : --nDepth;
2565  }
2566 
2567  typedef typename BinaryFunction<T>::BasePointer BasePointer;
2568  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
2569 
2570  BasePointer _simpl() const override
2571  {
2572  int i, j, k;
2573  BasePointer fZero = std::make_shared<Fconst<T>>();
2574  BasePointer fOne = std::make_shared<Fconst<T>>(CFUN_M_ONE);
2575  BasePointer fMOne = std::make_shared<Fconst<T>>(CFUN_M_MONE);
2576  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
2577  if (fCopy[0]->_equals(fZero)) // 0 / x = 0
2578  {
2579  return fZero;
2580  }
2581  if (fCopy[1]->_equals(fZero))
2582  { // x / 0 = inf
2583  return std::make_shared<Finfinity<T>>();
2584  }
2585  if (fCopy[1]->_kind() == CFUN_K_INFINITY ||
2586  fCopy[1]->_kind() == CFUN_K_MNINFINITY) // x / inf = 0 | x / -inf = 0
2587  {
2588  return fZero;
2589  }
2590  if (fCopy[1]->_equals(fOne))
2591  { // x / 1 = x
2592  return fCopy[0];
2593  }
2594  if (fCopy[1]->_equals(fMOne))
2595  { // x / -1 = -x
2596  return std::make_shared<Fuminus<T>>(fCopy[0]);
2597  }
2598  if (fCopy[0]->_kind() == CFUN_K_CONST &&
2599  fCopy[1]->_kind() == CFUN_K_CONST)
2600  { // 6 / 2 = 3
2601  T dNomin = fCopy[0]->_value(nullptr);
2602  T dDenom = fCopy[1]->_value(nullptr);
2603  if (cvm::_abs(dDenom) <= cvm::cvmMachMin())
2604  {
2605  if (Comparator<T,T>::lt(dNomin, CFUN_M_ZERO))
2606  {
2607  return std::make_shared<Fmninfinity<T>>();
2608  }
2609  else
2610  {
2611  return std::make_shared<Finfinity<T>>();
2612  }
2613  }
2614  else
2615  {
2616  return std::make_shared<Fconst<T>>(dNomin / dDenom);
2617  }
2618  }
2619  if (fCopy[0]->_equals(fCopy[1]))
2620  { // x / x = 1
2621  return std::make_shared<Fconst<T>>(CFUN_M_ONE);
2622  }
2623  if (fCopy[0]->_kind() == CFUN_K_UMINUS &&
2624  fCopy[1]->_kind() == CFUN_K_UMINUS)
2625  { // (-a)/(-b) = a/b)
2626  return
2627  std::make_shared<Fdiv<T>>(fCopy[0]->_getArg(0),
2628  fCopy[1]->_getArg(0))->_simp();
2629  }
2630  for (i = 0; i <= 1; ++i)
2631  {
2632  if (fCopy[i]->_kind() == CFUN_K_UMINUS)
2633  { // (-a)/b = -a/b
2634  BasePointer fTmp =
2635  i ?
2636  std::make_shared<Fuminus<T>>(std::make_shared<Fdiv<T>>(fCopy[__not(i)],
2637  fCopy[i]->_getArg(0)))
2638  :
2639  std::make_shared<Fuminus<T>>(std::make_shared<Fdiv<T>>(fCopy[i]->_getArg(0),
2640  fCopy[__not(i)]));
2641  return fTmp->_simp();
2642  }
2643  }
2644  if (fCopy[0]->_kind() == CFUN_K_POWER && // x^a/x^b=x^(a-b)
2645  fCopy[1]->_kind() == CFUN_K_POWER &&
2646  fCopy[0]->_getArg(0)->_equals(fCopy[1]->_getArg(0)))
2647  {
2648  return
2649  std::make_shared<Fpower<T>>(fCopy[0]->_getArg(0),
2650  std::make_shared<Fminus<T>>(fCopy[0]->_getArg(1),
2651  fCopy[1]->_getArg(1)))->_simp();
2652  }
2653  if (fCopy[0]->_kind() == CFUN_K_POWER && // x^a/x=x^(a-1)
2654  fCopy[0]->_getArg(0)->_equals(fCopy[1]))
2655  {
2656  return
2657  std::make_shared<Fpower<T>>(fCopy[1],
2658  std::make_shared<Fminus<T>>(fCopy[0]->_getArg(1),
2659  std::make_shared<Fconst<T>>(CFUN_M_ONE)))->_simp();
2660  }
2661  if (fCopy[1]->_kind() == CFUN_K_POWER && // x/x^a=x^(1-a)
2662  fCopy[1]->_getArg(0)->_equals(fCopy[0]))
2663  {
2664  return
2665  std::make_shared<Fpower<T>>(fCopy[0],
2666  std::make_shared<Fminus<T>>(std::make_shared<Fconst<T>>(CFUN_M_ONE),
2667  fCopy[1]->_getArg(1)))->_simp();
2668  }
2669 
2670  for (j = 0; j <= 1; ++j)
2671  {
2672  if (fCopy[j]->_kind() == CFUN_K_MULT)
2673  { // [x*a] / a | a / [x*a]
2674  for (i = 0; i <= 1; ++i)
2675  {
2676  BasePointer pNum = fCopy[j]->_getArg(i);
2677  BasePointer pDen = fCopy[__not(j)];
2678  BasePointer fTmp = std::make_shared<Fdiv<T>>(j ? pDen : pNum,
2679  j ? pNum : pDen);
2680  BasePointer fTmps(fTmp->_simp());
2681  if (!fTmp->_equals(fTmps))
2682  {
2683  if (j)
2684  {
2685  return
2686  std::make_shared<Fdiv<T>>(fTmps,
2687  fCopy[j]->_getArg(__not(i)))->_simp();
2688  }
2689  else
2690  {
2691  return
2692  std::make_shared<Fmult<T>>(fCopy[j]->_getArg(__not(i)),
2693  fTmps)->_simp();
2694  }
2695  }
2696  }
2697  if (fCopy[__not(j)]->_kind() == CFUN_K_MULT)
2698  { // x*a / x*b
2699  for (i = 0; i <= 1; ++i)
2700  {
2701  for (k = 0; k <= 1; ++k)
2702  {
2703  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(i),
2704  fCopy[__not(j)]->_getArg(k));
2705  BasePointer fTmps(fTmp->_simp());
2706  if (!fTmp->_equals(fTmps))
2707  {
2708  return
2709  std::make_shared<Fdiv<T>>(fTmps,
2710  std::make_shared<Fmult<T>>(fCopy[j]->_getArg(__not(i)),
2711  fCopy[__not(j)]->_getArg(__not(k))))->_simp();
2712  }
2713  }
2714  }
2715  }
2716 
2717  if (fCopy[__not(j)]->_kind() == CFUN_K_DIV)
2718  { // x*a / x/b | x/a / x*b
2719  if (!j)
2720  {
2721  return
2722  std::make_shared<Fmult<T>>(fCopy[0],
2723  std::make_shared<Fdiv<T>>(fCopy[1]->_getArg(1),
2724  fCopy[1]->_getArg(0)))->_simp();
2725  }
2726  else
2727  { // j==1, i.e. x/a / x*b
2728  for (i = 0; i <= 1; ++i)
2729  {
2730  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[0]->_getArg(0),
2731  fCopy[1]->_getArg(i));
2732  BasePointer fTmps(fTmp->_simp());
2733  if (!fTmp->_equals(fTmps))
2734  {
2735  return
2736  std::make_shared<Fdiv<T>>(fTmps,
2737  std::make_shared<Fmult<T>>(fCopy[0]->_getArg(1),
2738  fCopy[1]->_getArg(__not(i))))->_simp();
2739  }
2740  }
2741  for (i = 0; i <= 1; ++i)
2742  { // a/x / x*b
2743  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[0]->_getArg(1),
2744  fCopy[1]->_getArg(i));
2745  BasePointer fTmps(fTmp->_simp());
2746  if (!fTmp->_equals(fTmps))
2747  {
2748  return
2749  std::make_shared<Fdiv<T>>(std::make_shared<Fdiv<T>>(fCopy[0]->_getArg(0),
2750  fCopy[1]->_getArg(__not(i))),
2751  fTmps)->_simp();
2752  }
2753  }
2754  }
2755  }
2756  }
2757  if (fCopy[j]->_kind() == CFUN_K_DIV)
2758  { // a/x / a | a / a/x
2759  if (j)
2760  { // a / a/x == a * x/a
2761  return
2762  std::make_shared<Fmult<T>>(fCopy[0],
2763  std::make_shared<Fdiv<T>>(fCopy[1]->_getArg(1),
2764  fCopy[1]->_getArg(0)))->_simp();
2765  }
2766  else
2767  {
2768  { // j==0 i.e. a/x / a
2769  BasePointer fTmp = std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(0),
2770  fCopy[__not(j)]);
2771  BasePointer fTmps(fTmp->_simp());
2772  if (!fTmp->_equals(fTmps))
2773  {
2774  return
2775  std::make_shared<Fdiv<T>>(fTmps,
2776  fCopy[j]->_getArg(1))->_simp();
2777  }
2778  }
2779  {
2780  BasePointer fTmp = std::make_shared<Fmult<T>>(fCopy[j]->_getArg(1), // x/a / a
2781  fCopy[__not(j)]);
2782  BasePointer fTmps(fTmp->_simp());
2783  if (!fTmp->_equals(fTmps))
2784  {
2785  return
2786  std::make_shared<Fdiv<T>>(fCopy[j]->_getArg(0),
2787  fTmps)->_simp();
2788  }
2789  }
2790  }
2791  }
2792  }
2793  return std::make_shared<Fdiv<T>>(fCopy[0], fCopy[1]);
2794  }
2795 
2796 public:
2797  Fdiv(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
2798  : BinaryFunction<T>(pfSrc0, pfSrc1)
2799  {
2800  }
2801 
2802  Fdiv(const std::string& sDividend, const std::string& sDivisor,
2803  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2804  : BinaryFunction<T>(sDividend, sDivisor, saVars, saParameters, saMeanings)
2805  {
2806  }
2807 
2808  Fdiv(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
2809  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2810  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
2811  {
2812  }
2813 
2814  T _value(const T* pdVars) const override
2815  {
2816  T dDenom = this->mf1->_value(pdVars);
2817  if (Comparator<T,T>::eq(dDenom, CFUN_M_ZERO)) {
2819  }
2820  return this->mf0->_value(pdVars) / dDenom;
2821  }
2822 
2823  BasePointer _clone() const override {
2824  return std::make_shared<Fdiv<T>>(this->mf0, this->mf1);
2825  }
2826 
2827  BasePointer _deriv(size_t nVarNum) const override
2828  {
2829  return
2830  std::make_shared<Fdiv<T>>(std::make_shared<Fminus<T>>(std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
2831  this->mf1),
2832  std::make_shared<Fmult<T>>(this->mf0,
2833  this->mf1->_deriv(nVarNum))),
2834  std::make_shared<Fpower<T>>(this->mf1,
2835  std::make_shared<Fconst<T>>(CFUN_M_TWO)))->_simp();
2836  }
2837 
2838  std::string _format(int nPrecision) const override
2839  {
2840  std::ostringstream osBuf;
2841  switch (this->mf0->_kind()) {
2842  case CFUN_K_PLUS:
2843  case CFUN_K_MINUS:
2844  case CFUN_K_DIV:
2845  osBuf << CFUN_O_SPARENTH << this->mf0->_format(nPrecision) << CFUN_C_PARENTH << CFUN_SDIV;
2846  break;
2847  default:
2848  osBuf << this->mf0->_format(nPrecision) << CFUN_SDIV;
2849  break;
2850  }
2851  switch (this->mf1->_kind()) {
2852  case CFUN_K_PLUS:
2853  case CFUN_K_MINUS:
2854  case CFUN_K_UMINUS:
2855  case CFUN_K_MULT:
2856  case CFUN_K_DIV:
2857  osBuf << CFUN_O_SPARENTH << this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
2858  break;
2859  default:
2860  osBuf << this->mf1->_format(nPrecision);
2861  break;
2862  }
2863  return osBuf.str();
2864  }
2865 };
2866 
2867 template <typename T>
2868 class Fpower : public BinaryFunction<T>
2869 {
2870 private:
2871  int _kind() const override {
2872  return CFUN_K_POWER;
2873  }
2874 
2875 protected:
2876  int _depth(bool bAcquire) const override
2877  {
2878  static int nDepth;
2879  return bAcquire ? ++nDepth : --nDepth;
2880  }
2881 
2882  typedef typename BinaryFunction<T>::BasePointer BasePointer;
2883  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
2884 
2885  BasePointer _simpl() const override
2886  {
2887  BasePointer fZero = std::make_shared<Fconst<T>>();
2888  BasePointer fOne = std::make_shared<Fconst<T>>(CFUN_M_ONE);
2889  BasePointer fMOne = std::make_shared<Fconst<T>>(CFUN_M_MONE);
2890  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
2891  if (fCopy[1]->_equals(fZero))
2892  { // x^0 = 1
2893  return fOne;
2894  }
2895  else if (fCopy[0]->_equals(fZero))
2896  { // 0^x = 0
2897  return fZero;
2898  }
2899  else if (fCopy[1]->_equals(fOne))
2900  { // x^1 = x
2901  return fCopy[0];
2902  }
2903  else if (fCopy[0]->_kind() == CFUN_K_CONST &&
2904  fCopy[1]->_kind() == CFUN_K_CONST)
2905  { // 6^2 = 36
2906  return
2907  std::make_shared<Fconst<T>>(std::pow(fCopy[0]->_value(nullptr), fCopy[1]->_value(nullptr)));
2908  }
2909  else if (fCopy[1]->_equals(fMOne))
2910  { // x^-1 = 1/x
2911  return
2912  std::make_shared<Fdiv<T>>(fOne,
2913  fCopy[0]);
2914  }
2915  else if (fCopy[0]->_kind() == CFUN_K_POWER)
2916  { // [x^a]^b = x^[a*b]
2917  return
2918  std::make_shared<Fpower<T>>(fCopy[0]->_getArg(0),
2919  std::make_shared<Fmult<T>>(fCopy[0]->_getArg(1),
2920  fCopy[1]))->_simp();
2921  }
2922  return std::make_shared<Fpower<T>>(fCopy[0], fCopy[1]);
2923  }
2924 
2925 public:
2926  Fpower(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
2927  : BinaryFunction<T>(pfSrc0, pfSrc1)
2928  {
2929  }
2930 
2931  Fpower(const std::string& sBasis, const std::string& sExponent,
2932  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2933  : BinaryFunction<T>(sBasis, sExponent, saVars, saParameters, saMeanings)
2934  {
2935  }
2936 
2937  Fpower(const std::string& sBasisCommaExponent, size_t nFirst, size_t nLast,
2938  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2939  {
2940  this->BinCtr(sBasisCommaExponent, nFirst, nLast, saVars, saParameters, saMeanings);
2941  }
2942 
2943  Fpower(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
2944  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
2945  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
2946  {
2947  }
2948 
2949  T _value(const T* pdVars) const override {
2950  return std::pow(this->mf0->_value(pdVars), this->mf1->_value(pdVars));
2951  }
2952 
2953  BasePointer _clone() const override {
2954  return std::make_shared<Fpower<T>>(this->mf0, this->mf1);
2955  }
2956 
2957  BasePointer _deriv(size_t nVarNum) const override
2958  {
2959  return
2960  std::make_shared<Fplus<T>>(std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
2961  std::make_shared<Fmult<T>>(this->mf1,
2962  std::make_shared<Fpower<T>>(this->mf0,
2963  std::make_shared<Fplus<T>>(this->mf1,
2964  std::make_shared<Fconst<T>>(CFUN_M_MONE))))),
2965  std::make_shared<Fmult<T>>(this->mf1->_deriv(nVarNum),
2966  std::make_shared<Fmult<T>>(std::make_shared<Fpower<T>>(this->mf0,
2967  this->mf1),
2968  std::make_shared<Flog<T>>(this->mf0))))->_simp();
2969  }
2970 
2971  std::string _format(int nPrecision) const override
2972  {
2973  std::ostringstream osBuf;
2974  switch (this->mf0->_kind()) {
2975  case CFUN_K_PLUS:
2976  case CFUN_K_MINUS:
2977  case CFUN_K_MULT:
2978  case CFUN_K_DIV:
2979  case CFUN_K_POWER:
2980  case CFUN_K_UMINUS:
2981  osBuf << CFUN_O_SPARENTH << this->mf0->_format(nPrecision) << CFUN_C_SPARENTH << CFUN_SPOWER;
2982  break;
2983  default:
2984  osBuf << this->mf0->_format(nPrecision) << CFUN_SPOWER;
2985  break;
2986  }
2987  switch (this->mf1->_kind()) {
2988  case CFUN_K_PLUS:
2989  case CFUN_K_MINUS:
2990  case CFUN_K_MULT:
2991  case CFUN_K_DIV:
2992  case CFUN_K_POWER:
2993  case CFUN_K_UMINUS:
2994  osBuf << CFUN_O_SPARENTH << this->mf1->_format(nPrecision) << CFUN_C_SPARENTH;
2995  break;
2996  default:
2997  osBuf << this->mf1->_format(nPrecision);
2998  break;
2999  }
3000  return osBuf.str();
3001  }
3002 };
3003 
3004 template <typename T>
3005 class Fsat : public BinaryFunction<T>
3006 {
3007 private:
3008  int _kind() const override {
3009  return CFUN_K_SAT;
3010  }
3011 
3012 protected:
3013  int _depth(bool bAcquire) const override
3014  {
3015  static int nDepth;
3016  return bAcquire ? ++nDepth : --nDepth;
3017  }
3018 
3019  typedef typename BinaryFunction<T>::BasePointer BasePointer;
3020  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
3021 
3022  BasePointer _simpl() const override
3023  {
3024  BasePointer fZero = std::make_shared<Fconst<T>>();
3025  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
3026  if (fCopy[0]->_equals(fZero)) {
3027  return fZero;
3028  }
3029  return std::make_shared<Fsat<T>>(fCopy[0], fCopy[1]);
3030  }
3031 
3032 public:
3033  Fsat(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
3034  : BinaryFunction<T>(pfSrc0, pfSrc1)
3035  {
3036  }
3037 
3038  Fsat(const std::string& sFun, const std::string& sDelta,
3039  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3040  : BinaryFunction<T>(sFun, sDelta, saVars, saParameters, saMeanings)
3041  {
3042  }
3043 
3044  Fsat(const std::string& sFunCommaDelta, size_t nFirst, size_t nLast,
3045  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3046  {
3047  this->BinCtr(sFunCommaDelta, nFirst, nLast, saVars, saParameters, saMeanings);
3048  }
3049 
3050  Fsat(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
3051  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3052  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
3053  {
3054  }
3055 
3056  T _value(const T* pdVars) const override {
3057  return Helper<T>::_value(this->mf0.get(), this->mf1.get(), pdVars);
3058  }
3059 
3060  BasePointer _clone() const override {
3061  return std::make_shared<Fsat<T>>(this->mf0, this->mf1);
3062  }
3063 
3064  BasePointer _deriv(size_t) const override
3065  {
3066  return
3067  std::make_shared<Fplus<T>>(std::make_shared<Fdelta<T>>(this->mf0,
3068  this->mf1),
3069  std::make_shared<Fdelta<T>>(this->mf0,
3070  std::make_shared<Fuminus<T>>(this->mf1)))->_simp();
3071  }
3072 
3073  std::string _format(int nPrecision) const override
3074  {
3075  std::ostringstream osBuf;
3076  osBuf << CFUN_SAT << CFUN_O_PARENTH << this->mf0->_format(nPrecision) << CFUN_SCOMMA <<
3077  this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
3078  return osBuf.str();
3079  }
3080 
3081 protected:
3083  template<typename U>
3084  class Helper {
3085  public:
3086  static U _value(const BaseFunction<U>* pfArg0, BaseFunction<U>* pfArg1, const U* pdVars)
3087  {
3088  U dRes = CFUN_M_ZERO;
3089  const U dMeans = pfArg0->_value(pdVars);
3090  const U dDelta = cvm::_abs(pfArg1->_value(pdVars));
3091  if (dMeans > dDelta) {
3092  dRes = CFUN_M_ONE;
3093  }
3094  else if (dMeans < -dDelta) {
3095  dRes = CFUN_M_MONE;
3096  }
3097  return dRes;
3098  }
3099  };
3100 
3101  template<typename U>
3102  class Helper<std::complex<U> > {
3103  typedef std::complex<U> UC;
3104  public:
3105  static UC _value(const BaseFunction<UC>* pfArg0, BaseFunction<UC>* pfArg1, const UC* pdVars)
3106  {
3107  UC dRes = CFUN_M_ZERO;
3108  const U dMeans = pfArg0->_value(pdVars).real();
3109  const U dDelta = cvm::_abs(pfArg1->_value(pdVars).real());
3110  if (dMeans > dDelta) {
3111  dRes = CFUN_M_ONE;
3112  }
3113  else if (dMeans < -dDelta) {
3114  dRes = CFUN_M_MONE;
3115  }
3116  return dRes;
3117  }
3118  };
3120 };
3121 
3122 template <typename T>
3123 class Fexp : public UnaryFunction<T>
3124 {
3125 private:
3126  int _kind() const override {
3127  return CFUN_K_EXP;
3128  }
3129 
3130 protected:
3131  int _depth(bool bAcquire) const override
3132  {
3133  static int nDepth;
3134  return bAcquire ? ++nDepth : --nDepth;
3135  }
3136 
3137  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3138 
3139  BasePointer _simpl() const override
3140  {
3141  BasePointer fCopy(this->mf0->_simp());
3142  if (fCopy->_kind() == CFUN_K_CONST) {
3143  return std::make_shared<Fconst<T>>(std::exp(fCopy->_value(nullptr)));
3144  }
3145  return std::make_shared<Fexp<T>>(fCopy);
3146  }
3147 
3148 public:
3149  Fexp(const BasePointer& pfSrc)
3150  : UnaryFunction<T>(pfSrc)
3151  {
3152  }
3153 
3154  Fexp(const std::string& sArg,
3155  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3156  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3157  {
3158  }
3159 
3160  Fexp(const std::string& sArg, size_t nF, size_t nL,
3161  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3162  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3163  {
3164  }
3165 
3166  T _value(const T* pdVars) const override {
3167  return std::exp(this->mf0->_value(pdVars));
3168  }
3169 
3170  BasePointer _clone() const override {
3171  return std::make_shared<Fexp<T>>(this->mf0);
3172  }
3173 
3174  BasePointer _deriv(size_t nVarNum) const override
3175  {
3176  return
3177  std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
3178  std::make_shared<Fexp<T>>(this->mf0))->_simp();
3179  }
3180 
3181  const char* _name() const override
3182  {
3183  static const char sz_exp[] = CFUN_EXP;
3184  return sz_exp;
3185  }
3186 };
3187 
3188 template <typename T>
3189 class Fsqrt : public UnaryFunction<T>
3190 {
3191 private:
3192  int _kind() const override {
3193  return CFUN_K_SQRT;
3194  }
3195 
3196 protected:
3197  int _depth(bool bAcquire) const override
3198  {
3199  static int nDepth;
3200  return bAcquire ? ++nDepth : --nDepth;
3201  }
3202 
3203  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3204 
3205  BasePointer _simpl() const override
3206  {
3207  BasePointer fCopy(this->mf0->_simp());
3208  if (fCopy->_kind() == CFUN_K_CONST) {
3209  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::sqrt(fCopy->_value(nullptr)));
3210  }
3211  return std::make_shared<Fsqrt<T>>(fCopy);
3212  }
3213 
3214 public:
3215  Fsqrt(const BasePointer& pfSrc)
3216  : UnaryFunction<T>(pfSrc)
3217  {
3218  }
3219 
3220  Fsqrt(const std::string& sArg,
3221  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3222  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3223  {
3224  }
3225 
3226  Fsqrt(const std::string& sArg, size_t nF, size_t nL,
3227  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3228  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3229  {
3230  }
3231 
3232  T _value(const T* pdVars) const override {
3233  return ElementaryFunctions<T>::sqrt(this->mf0->_value(pdVars));
3234  }
3235 
3236  BasePointer _clone() const override {
3237  return std::make_shared<Fsqrt<T>>(this->mf0);
3238  }
3239 
3240  BasePointer _deriv(size_t nVarNum) const override
3241  {
3242  return
3243  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3244  std::make_shared<Fmult<T>>(std::make_shared<Fconst<T>>(CFUN_M_TWO),
3245  std::make_shared<Fsqrt<T>>(this->mf0)))->_simp();
3246  }
3247 
3248  const char* _name() const override
3249  {
3250  static const char sz_sqrt[] = CFUN_SQRT;
3251  return sz_sqrt;
3252  }
3253 };
3254 
3255 template <typename T>
3256 class Flog : public UnaryFunction<T>
3257 {
3258 private:
3259  int _kind() const override {
3260  return CFUN_K_LOG;
3261  }
3262 
3263 protected:
3264  int _depth(bool bAcquire) const override
3265  {
3266  static int nDepth;
3267  return bAcquire ? ++nDepth : --nDepth;
3268  }
3269 
3270  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3271 
3272  BasePointer _simpl() const override
3273  {
3274  BasePointer fZero = std::make_shared<Fconst<T>>();
3275  BasePointer fCopy(this->mf0->_simp());
3276  if (fCopy->_equals(fZero))
3277  { // log 0 = - inf
3278  return std::make_shared<Fmninfinity<T>>();
3279  }
3280  else if (fCopy->_kind() == CFUN_K_CONST)
3281  { // log 1 = 0
3282  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::log(fCopy->_value(nullptr)));
3283  }
3284  else if (fCopy->_kind() == CFUN_K_SQRT)
3285  { // log sqrt (x) = 0.5 * log (x)
3286  return
3287  std::make_shared<Fmult<T>>(std::make_shared<Flog<T>>(fCopy->_getArg(0)),
3288  std::make_shared<Fconst<T>>(CFUN_M_HALF))->_simp();
3289  }
3290  else if (fCopy->_kind() == CFUN_K_POWER)
3291  { // log (x^y) = y * log (x)
3292  return
3293  std::make_shared<Fmult<T>>(std::make_shared<Flog<T>>(fCopy->_getArg(0)),
3294  fCopy->_getArg(1))->_simp();
3295  }
3296  return std::make_shared<Flog<T>>(fCopy);
3297  }
3298 
3299 public:
3300  Flog(const BasePointer& pfSrc)
3301  : UnaryFunction<T>(pfSrc)
3302  {
3303  }
3304 
3305  Flog(const std::string& sArg,
3306  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3307  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3308  {
3309  }
3310 
3311  Flog(const std::string& sArg, size_t nF, size_t nL,
3312  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3313  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3314  {
3315  }
3316 
3317  T _value(const T* pdVars) const override {
3318  return ElementaryFunctions<T>::log(this->mf0->_value(pdVars));
3319  }
3320 
3321  BasePointer _clone() const override {
3322  return std::make_shared<Flog<T>>(this->mf0);
3323  }
3324 
3325  BasePointer _deriv(size_t nVarNum) const override
3326  {
3327  return
3328  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3329  this->mf0)->_simp();
3330  }
3331 
3332  const char* _name() const override
3333  {
3334  static const char sz_log[] = CFUN_LOG;
3335  return sz_log;
3336  }
3337 };
3338 
3339 template <typename T>
3340 class Flog10 : public UnaryFunction<T>
3341 {
3342 private:
3343  int _kind() const override {
3344  return CFUN_K_LOG10;
3345  }
3346 
3347 protected:
3348  int _depth(bool bAcquire) const override
3349  {
3350  static int nDepth;
3351  return bAcquire ? ++nDepth : --nDepth;
3352  }
3353 
3354  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3355 
3356  BasePointer _simpl() const override
3357  {
3358  BasePointer fZero = std::make_shared<Fconst<T>>();
3359  BasePointer fCopy(this->mf0->_simp());
3360  if (fCopy->_equals(fZero))
3361  {
3362  return std::make_shared<Fmninfinity<T>>();
3363  }
3364  else if (fCopy->_kind() == CFUN_K_CONST)
3365  {
3366  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::log10(fCopy->_value(nullptr)));
3367  }
3368  else if (fCopy->_kind() == CFUN_K_SQRT)
3369  { // log sqrt (x) = 0.5 * log (x)
3370  return
3371  std::make_shared<Fmult<T>>(std::make_shared<Flog10<T>>(fCopy->_getArg(0)),
3372  std::make_shared<Fconst<T>>(CFUN_M_HALF))->_simp();
3373  }
3374  else if (fCopy->_kind() == CFUN_K_POWER)
3375  { // log (x^y) = y * log (x)
3376  return
3377  std::make_shared<Fmult<T>>(std::make_shared<Flog10<T>>(fCopy->_getArg(0)),
3378  fCopy->_getArg(1))->_simp();
3379  }
3380  return std::make_shared<Flog10<T>>(fCopy);
3381  }
3382 
3383 public:
3384  Flog10(const BasePointer& pfSrc)
3385  : UnaryFunction<T>(pfSrc)
3386  {
3387  }
3388 
3389  Flog10(const std::string& sArg,
3390  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3391  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3392  {
3393  }
3394 
3395  Flog10(const std::string& sArg, size_t nF, size_t nL,
3396  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3397  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3398  {
3399  }
3400 
3401  T _value(const T* pdVars) const override {
3402  return ElementaryFunctions<T>::log10(this->mf0->_value(pdVars));
3403  }
3404 
3405  BasePointer _clone() const override {
3406  return std::make_shared<Flog10<T>>(*this);
3407  }
3408 
3409  BasePointer _deriv(size_t nVarNum) const override
3410  {
3411  return
3412  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3413  std::make_shared<Fmult<T>>(std::make_shared<Fconst<T>>(CFUN_M_LN_10),
3414  this->mf0))->_simp();
3415  }
3416 
3417  const char* _name() const override
3418  {
3419  static const char sz_log10[] = CFUN_LOG10;
3420  return sz_log10;
3421  }
3422 };
3423 
3424 template <typename T>
3425 class Fsin : public UnaryFunction<T>
3426 {
3427 private:
3428  int _kind() const override {
3429  return CFUN_K_SIN;
3430  }
3431 
3432 protected:
3433  int _depth(bool bAcquire) const override
3434  {
3435  static int nDepth;
3436  return bAcquire ? ++nDepth : --nDepth;
3437  }
3438 
3439  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3440 
3441  BasePointer _simpl() const override
3442  {
3443  BasePointer fCopy(this->mf0->_simp());
3444  if (fCopy->_kind() == CFUN_K_CONST) {
3445  return std::make_shared<Fconst<T>>(std::sin(fCopy->_value(nullptr)));
3446  }
3447  return std::make_shared<Fsin<T>>(fCopy);
3448  }
3449 
3450 public:
3451  Fsin(const BasePointer& pfSrc)
3452  : UnaryFunction<T>(pfSrc)
3453  {
3454  }
3455 
3456  Fsin(const std::string& sArg,
3457  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3458  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3459  {
3460  }
3461 
3462  Fsin(const std::string& sArg, size_t nF, size_t nL,
3463  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3464  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3465  {
3466  }
3467 
3468  T _value(const T* pdVars) const override {
3469  return std::sin(this->mf0->_value(pdVars));
3470  }
3471 
3472  BasePointer _clone() const override {
3473  return std::make_shared<Fsin<T>>(this->mf0);
3474  }
3475 
3476  BasePointer _deriv(size_t nVarNum) const override
3477  {
3478  return
3479  std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
3480  std::make_shared<Fcos<T>>(this->mf0))->_simp();
3481  }
3482 
3483  const char* _name() const override
3484  {
3485  static const char sz_sin[] = CFUN_SIN;
3486  return sz_sin;
3487  }
3488 };
3489 
3490 template <typename T>
3491 class Fcos : public UnaryFunction<T> {
3492 private:
3493  int _kind() const override {
3494  return CFUN_K_COS;
3495  }
3496 
3497 protected:
3498  int _depth(bool bAcquire) const override
3499  {
3500  static int nDepth;
3501  return bAcquire ? ++nDepth : --nDepth;
3502  }
3503 
3504  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3505 
3506  BasePointer _simpl() const override
3507  {
3508  BasePointer fCopy(this->mf0->_simp());
3509  if (fCopy->_kind() == CFUN_K_CONST) {
3510  return std::make_shared<Fconst<T>>(std::cos(fCopy->_value(nullptr)));
3511  }
3512  return std::make_shared<Fcos<T>>(fCopy);
3513  }
3514 
3515 public:
3516  Fcos(const BasePointer& pfSrc)
3517  : UnaryFunction<T>(pfSrc)
3518  {
3519  }
3520 
3521  Fcos(const std::string& sArg,
3522  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3523  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3524  {
3525  }
3526 
3527  Fcos(const std::string& sArg, size_t nF, size_t nL,
3528  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3529  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3530  {
3531  }
3532 
3533  T _value(const T* pdVars) const override {
3534  return std::cos(this->mf0->_value(pdVars));
3535  }
3536 
3537  BasePointer _clone() const override {
3538  return std::make_shared<Fcos<T>>(this->mf0);
3539  }
3540 
3541  BasePointer _deriv(size_t nVarNum) const override
3542  {
3543  return
3544  std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
3545  std::make_shared<Fuminus<T>>(std::make_shared<Fsin<T>>(this->mf0)))->_simp();
3546  }
3547 
3548  const char* _name() const override
3549  {
3550  static const char sz_cos[] = CFUN_COS;
3551  return sz_cos;
3552  }
3553 };
3554 
3555 template <typename T>
3556 class Ftan : public UnaryFunction<T>
3557 {
3558 private:
3559  int _kind() const override {
3560  return CFUN_K_TAN;
3561  }
3562 
3563 protected:
3564  int _depth(bool bAcquire) const override
3565  {
3566  static int nDepth;
3567  return bAcquire ? ++nDepth : --nDepth;
3568  }
3569 
3570  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3571 
3572  BasePointer _simpl() const override
3573  {
3574  BasePointer fCopy(this->mf0->_simp());
3575  if (fCopy->_kind() == CFUN_K_CONST) {
3576  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::tan(fCopy->_value(nullptr)));
3577  }
3578  return std::make_shared<Ftan<T>>(fCopy);
3579  }
3580 
3581 public:
3582  Ftan(const BasePointer& pfSrc)
3583  : UnaryFunction<T>(pfSrc)
3584  {
3585  }
3586 
3587  Ftan(const std::string& sArg,
3588  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3589  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3590  {
3591  }
3592 
3593  Ftan(const std::string& sArg, size_t nF, size_t nL,
3594  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3595  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3596  {
3597  }
3598 
3599  T _value(const T* pdVars) const override {
3600  return ElementaryFunctions<T>::tan(this->mf0->_value(pdVars));
3601  }
3602 
3603  BasePointer _clone() const override {
3604  return std::make_shared<Ftan<T>>(this->mf0);
3605  }
3606 
3607  BasePointer _deriv(size_t nVarNum) const override
3608  {
3609  return
3610  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3611  std::make_shared<Fpower<T>>(std::make_shared<Fcos<T>>(this->mf0),
3612  std::make_shared<Fconst<T>>(CFUN_M_TWO)))->_simp();
3613  }
3614 
3615  const char* _name() const override
3616  {
3617  static const char sz_tan[] = CFUN_TAN;
3618  return sz_tan;
3619  }
3620 };
3621 
3622 template <typename T>
3623 class Fasin : public UnaryFunction<T>
3624 {
3625 private:
3626  int _kind() const override {
3627  return CFUN_K_ARCSIN;
3628  }
3629 
3630 protected:
3631  int _depth(bool bAcquire) const override
3632  {
3633  static int nDepth;
3634  return bAcquire ? ++nDepth : --nDepth;
3635  }
3636 
3637  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3638 
3639  BasePointer _simpl() const override
3640  {
3641  BasePointer fCopy(this->mf0->_simp());
3642  if (fCopy->_kind() == CFUN_K_CONST) {
3643  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::asin(fCopy->_value(nullptr)));
3644  }
3645  return std::make_shared<Fasin<T>>(fCopy);
3646  }
3647 
3648 public:
3649  Fasin(const BasePointer& pfSrc)
3650  : UnaryFunction<T>(pfSrc)
3651  {
3652  }
3653 
3654  Fasin(const std::string& sArg,
3655  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3656  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3657  {
3658  }
3659 
3660  Fasin(const std::string& sArg, size_t nF, size_t nL,
3661  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3662  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3663  {
3664  }
3665 
3666  T _value(const T* pdVars) const override {
3667  return ElementaryFunctions<T>::asin(this->mf0->_value(pdVars));
3668  }
3669 
3670  BasePointer _clone() const override {
3671  return std::make_shared<Fasin<T>>(this->mf0);
3672  }
3673 
3674  BasePointer _deriv(size_t nVarNum) const override
3675  {
3676  return
3677  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3678  std::make_shared<Fsqrt<T>>(std::make_shared<Fminus<T>>(std::make_shared<Fconst<T>>(CFUN_M_ONE),
3679  std::make_shared<Fpower<T>>(this->mf0,
3680  std::make_shared<Fconst<T>>(CFUN_M_TWO)))))->_simp();
3681  }
3682 
3683  const char* _name() const override
3684  {
3685  static const char sz_asin[] = CFUN_ASIN;
3686  return sz_asin;
3687  }
3688 };
3689 
3690 template <typename T>
3691 class Facos : public UnaryFunction<T>
3692 {
3693 private:
3694  int _kind() const override {
3695  return CFUN_K_ARCCOS;
3696  }
3697 
3698 protected:
3699  int _depth(bool bAcquire) const override
3700  {
3701  static int nDepth;
3702  return bAcquire ? ++nDepth : --nDepth;
3703  }
3704 
3705  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3706 
3707  BasePointer _simpl() const override
3708  {
3709  BasePointer fCopy(this->mf0->_simp());
3710  if (fCopy->_kind() == CFUN_K_CONST) {
3711  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::acos(fCopy->_value(nullptr)));
3712  }
3713  return std::make_shared<Facos<T>>(fCopy);
3714  }
3715 
3716 public:
3717  Facos(const BasePointer& pfSrc)
3718  : UnaryFunction<T>(pfSrc)
3719  {
3720  }
3721 
3722  Facos(const std::string& sArg,
3723  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3724  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3725  {
3726  }
3727 
3728  Facos(const std::string& sArg, size_t nF, size_t nL,
3729  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3730  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3731  {
3732  }
3733 
3734  T _value(const T* pdVars) const override {
3735  return ElementaryFunctions<T>::acos(this->mf0->_value(pdVars));
3736  }
3737 
3738  BasePointer _clone() const override {
3739  return std::make_shared<Facos<T>>(this->mf0);
3740  }
3741 
3742  BasePointer _deriv(size_t nVarNum) const override
3743  {
3744  return
3745  std::make_shared<Fuminus<T>>(std::make_shared<Fasin<T>>(this->mf0)->_deriv(nVarNum))->_simp();
3746  }
3747 
3748  const char* _name() const override
3749  {
3750  static const char sz_acos[] = CFUN_ACOS;
3751  return sz_acos;
3752  }
3753 };
3754 
3755 template <typename T>
3756 class Fatan : public UnaryFunction<T>
3757 {
3758 private:
3759  int _kind() const override {
3760  return CFUN_K_ARCTAN;
3761  }
3762 
3763 protected:
3764  int _depth(bool bAcquire) const override
3765  {
3766  static int nDepth;
3767  return bAcquire ? ++nDepth : --nDepth;
3768  }
3769 
3770  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3771 
3772  BasePointer _simpl() const override
3773  {
3774  BasePointer fCopy(this->mf0->_simp());
3775  if (fCopy->_kind() == CFUN_K_CONST) {
3776  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::atan(fCopy->_value(nullptr)));
3777  }
3778  return std::make_shared<Fatan<T>>(fCopy);
3779  }
3780 
3781 public:
3782  Fatan(const BasePointer& pfSrc)
3783  : UnaryFunction<T>(pfSrc)
3784  {
3785  }
3786 
3787  Fatan(const std::string& sArg,
3788  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3789  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3790  {
3791  }
3792 
3793  Fatan(const std::string& sArg, size_t nF, size_t nL,
3794  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3795  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3796  {
3797  }
3798 
3799  T _value(const T* pdVars) const override {
3800  return ElementaryFunctions<T>::atan(this->mf0->_value(pdVars));
3801  }
3802 
3803  BasePointer _clone() const override {
3804  return std::make_shared<Fatan<T>>(this->mf0);
3805  }
3806 
3807  BasePointer _deriv(size_t nVarNum) const override
3808  {
3809  return
3810  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
3811  std::make_shared<Fplus<T>>(std::make_shared<Fconst<T>>(CFUN_M_ONE),
3812  std::make_shared<Fpower<T>>(this->mf0,
3813  std::make_shared<Fconst<T>>(CFUN_M_TWO))))->_simp();
3814  }
3815 
3816  const char* _name() const override
3817  {
3818  static const char sz_atan[] = CFUN_ATAN;
3819  return sz_atan;
3820  }
3821 };
3822 
3823 
3824 template <typename T>
3825 class Fsinh : public UnaryFunction<T>
3826 {
3827 private:
3828  int _kind() const override {
3829  return CFUN_K_SINH;
3830  }
3831 
3832 protected:
3833  int _depth(bool bAcquire) const override
3834  {
3835  static int nDepth;
3836  return bAcquire ? ++nDepth : --nDepth;
3837  }
3838 
3839  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3840 
3841  BasePointer _simpl() const override
3842  {
3843  BasePointer fCopy(this->mf0->_simp());
3844  if (fCopy->_kind() == CFUN_K_CONST) {
3845  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::sinh(fCopy->_value(nullptr)));
3846  }
3847  return std::make_shared<Fsinh<T>>(fCopy);
3848  }
3849 
3850 public:
3851  Fsinh(const BasePointer& pfSrc)
3852  : UnaryFunction<T>(pfSrc)
3853  {
3854  }
3855 
3856  Fsinh(const std::string& sArg,
3857  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3858  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3859  {
3860  }
3861 
3862  Fsinh(const std::string& sArg, size_t nF, size_t nL,
3863  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3864  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3865  {
3866  }
3867 
3868  T _value(const T* pdVars) const override {
3869  return ElementaryFunctions<T>::sinh(this->mf0->_value(pdVars));
3870  }
3871 
3872  BasePointer _clone() const override {
3873  return std::make_shared<Fsinh<T>>(this->mf0);
3874  }
3875 
3876  BasePointer _deriv(size_t nVarNum) const override
3877  {
3878  return
3879  std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
3880  std::make_shared<Fcosh<T>>(this->mf0))->_simp();
3881  }
3882 
3883  const char* _name() const override
3884  {
3885  static const char sz_sinh[] = CFUN_SINH;
3886  return sz_sinh;
3887  }
3888 };
3889 
3890 
3891 template <typename T>
3892 class Fcosh : public UnaryFunction<T>
3893 {
3894 private:
3895  int _kind() const override {
3896  return CFUN_K_COSH;
3897  }
3898 
3899 protected:
3900  int _depth(bool bAcquire) const override
3901  {
3902  static int nDepth;
3903  return bAcquire ? ++nDepth : --nDepth;
3904  }
3905 
3906  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3907 
3908  BasePointer _simpl() const override
3909  {
3910  BasePointer fCopy(this->mf0->_simp());
3911  if (fCopy->_kind() == CFUN_K_CONST) {
3912  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::cosh(fCopy->_value(nullptr)));
3913  }
3914  return std::make_shared<Fcosh<T>>(fCopy);
3915  }
3916 
3917 public:
3918  Fcosh(const BasePointer& pfSrc)
3919  : UnaryFunction<T>(pfSrc)
3920  {
3921  }
3922 
3923  Fcosh(const std::string& sArg,
3924  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3925  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3926  {
3927  }
3928 
3929  Fcosh(const std::string& sArg, size_t nF, size_t nL,
3930  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3931  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3932  {
3933  }
3934 
3935  T _value(const T* pdVars) const override {
3936  return ElementaryFunctions<T>::cosh(this->mf0->_value(pdVars));
3937  }
3938 
3939  BasePointer _clone() const override {
3940  return std::make_shared<Fcosh<T>>(this->mf0);
3941  }
3942 
3943  BasePointer _deriv(size_t nVarNum) const override
3944  {
3945  return
3946  std::make_shared<Fmult<T>>(this->mf0->_deriv(nVarNum),
3947  std::make_shared<Fuminus<T>>(std::make_shared<Fsinh<T>>(this->mf0)))->_simp();
3948  }
3949 
3950  const char* _name() const override
3951  {
3952  static const char sz_cosh[] = CFUN_COSH;
3953  return sz_cosh;
3954  }
3955 };
3956 
3957 
3958 template <typename T>
3959 class Ftanh : public UnaryFunction<T>
3960 {
3961 private:
3962  int _kind() const override {
3963  return CFUN_K_TANH;
3964  }
3965 
3966 protected:
3967  int _depth(bool bAcquire) const override
3968  {
3969  static int nDepth;
3970  return bAcquire ? ++nDepth : --nDepth;
3971  }
3972 
3973  typedef typename UnaryFunction<T>::BasePointer BasePointer;
3974 
3975  BasePointer _simpl() const override
3976  {
3977  BasePointer fCopy(this->mf0->_simp());
3978  if (fCopy->_kind() == CFUN_K_CONST) {
3979  return std::make_shared<Fconst<T>>(ElementaryFunctions<T>::tanh(fCopy->_value(nullptr)));
3980  }
3981  return std::make_shared<Ftanh<T>>(fCopy);
3982  }
3983 
3984 public:
3985  Ftanh(const BasePointer& pfSrc)
3986  : UnaryFunction<T>(pfSrc)
3987  {
3988  }
3989 
3990  Ftanh(const std::string& sArg,
3991  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3992  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
3993  {
3994  }
3995 
3996  Ftanh(const std::string& sArg, size_t nF, size_t nL,
3997  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
3998  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
3999  {
4000  }
4001 
4002  T _value(const T* pdVars) const override {
4003  return ElementaryFunctions<T>::tanh(this->mf0->_value(pdVars));
4004  }
4005 
4006  BasePointer _clone() const override {
4007  return std::make_shared<Ftanh<T>>(this->mf0);
4008  }
4009 
4010  BasePointer _deriv(size_t nVarNum) const override
4011  {
4012  return
4013  std::make_shared<Fdiv<T>>(this->mf0->_deriv(nVarNum),
4014  std::make_shared<Fpower<T>>(std::make_shared<Fcosh<T>>(this->mf0),
4015  std::make_shared<Fconst<T>>(CFUN_M_TWO)))->_simp();
4016  }
4017 
4018  const char* _name() const override
4019  {
4020  static const char sz_tanh[] = CFUN_TANH;
4021  return sz_tanh;
4022  }
4023 };
4024 
4025 template <typename T>
4026 class Fsinint : public UnaryFunction<T>
4027 {
4028 private:
4029  int _kind() const override {
4030  return CFUN_K_INTSIN;
4031  }
4032 
4033 protected:
4034  int _depth(bool bAcquire) const override {
4035  static int nDepth;
4036  return bAcquire ? ++nDepth : --nDepth;
4037  }
4038 
4039  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4040 
4041  BasePointer _simpl() const override
4042  {
4043  BasePointer fCopy(this->mf0->_simp());
4044  if (fCopy->_kind() == CFUN_K_CONST) {
4045  return std::make_shared<Fconst<T>>(Helper<T>::_value(fCopy.get(), nullptr));
4046  }
4047  return std::make_shared<Fsinint<T>>(fCopy);
4048  }
4049 
4050 public:
4051  Fsinint(const BasePointer& pfSrc)
4052  : UnaryFunction<T>(pfSrc)
4053  {
4054  }
4055 
4056  Fsinint(const std::string& sArg,
4057  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4058  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
4059  {
4060  }
4061 
4062  Fsinint(const std::string& sArg, size_t nF, size_t nL,
4063  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4064  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
4065  {
4066  }
4067 
4068  T _value(const T* pdVars) const override {
4069  return Helper<T>::_value(this->mf0.get(), pdVars);
4070  }
4071 
4072  BasePointer _clone() const override {
4073  return std::make_shared<Fsinint<T>>(this->mf0);
4074  }
4075 
4076  BasePointer _deriv(size_t) const override
4077  {
4078  return
4079  std::make_shared<Fdiv<T>>(std::make_shared<Fsin<T>>(this->mf0),
4080  this->mf0)->_simp();
4081  }
4082 
4083  const char* _name() const override
4084  {
4085  static const char sz_si[] = CFUN_SI;
4086  return sz_si;
4087  }
4088 
4089 protected:
4091  template<typename U>
4092  class Helper {
4093  public:
4094  static U _value(const BaseFunction<U>* pfArg, const U* pdVars)
4095  {
4096  return ElementaryFunctions<U>::sinint(pfArg->_value(pdVars), basic_cvmMachSp<U>());
4097  }
4098  };
4099  template<typename U>
4100  class Helper<std::complex<U> > {
4101  typedef std::complex<U> UC;
4102  public:
4103  static UC _value(const BaseFunction<UC>* pfArg, const UC* pdVars)
4104  {
4105  return ElementaryFunctions<UC>::sinint(pfArg->_value(pdVars), basic_cvmMachSp<U>());
4106  }
4107  };
4109 };
4110 
4111 template <typename T>
4112 class Fcosint : public UnaryFunction<T>
4113 {
4114 private:
4115  int _kind() const override {
4116  return CFUN_K_INTCOS;
4117  }
4118 
4119 protected:
4120  int _depth(bool bAcquire) const override
4121  {
4122  static int nDepth;
4123  return bAcquire ? ++nDepth : --nDepth;
4124  }
4125 
4126  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4127 
4128  BasePointer _simpl() const override
4129  {
4130  BasePointer fCopy(this->mf0->_simp());
4131  if (fCopy->_kind() == CFUN_K_CONST) {
4132  return std::make_shared<Fconst<T>>(Helper<T>::_value(fCopy.get(), nullptr));
4133  }
4134  return std::make_shared<Fcosint<T>>(fCopy);
4135  }
4136 
4137 public:
4138  Fcosint(const BasePointer& pfSrc)
4139  : UnaryFunction<T>(pfSrc)
4140  {
4141  }
4142 
4143  Fcosint(const std::string& sArg,
4144  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4145  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
4146  {
4147  }
4148 
4149  Fcosint(const std::string& sArg, size_t nF, size_t nL,
4150  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4151  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
4152  {
4153  }
4154 
4155  T _value(const T* pdVars) const override {
4156  return Helper<T>::_value(this->mf0.get(), pdVars);
4157  }
4158 
4159  BasePointer _clone() const override {
4160  return std::make_shared<Fcosint<T>>(this->mf0);
4161  }
4162 
4163  BasePointer _deriv(size_t) const override
4164  {
4165  return
4166  std::make_shared<Fdiv<T>>(std::make_shared<Fcos<T>>(this->mf0),
4167  this->mf0)->_simp();
4168  }
4169 
4170  const char* _name() const override
4171  {
4172  static const char sz_ci[] = CFUN_CI;
4173  return sz_ci;
4174  }
4175 
4176 protected:
4178  template<typename U>
4179  class Helper {
4180  public:
4181  static U _value(const BaseFunction<U>* pfArg, const U* pdVars)
4182  {
4183  return ElementaryFunctions<U>::cosint(pfArg->_value(pdVars), basic_cvmMachSp<U>());
4184  }
4185  };
4186  template<typename U>
4187  class Helper<std::complex<U> > {
4188  typedef std::complex<U> UC;
4189  public:
4190  static UC _value(const BaseFunction<UC>* pfArg, const UC* pdVars)
4191  {
4192  return ElementaryFunctions<UC>::cosint(pfArg->_value(pdVars), basic_cvmMachSp<U>());
4193  }
4194  };
4196 };
4197 
4198 template <typename T>
4199 class Fuminus : public UnaryFunction<T>
4200 {
4201 private:
4202  int _kind() const override {
4203  return CFUN_K_UMINUS;
4204  }
4205 
4206 protected:
4207  int _depth(bool bAcquire) const override
4208  {
4209  static int nDepth;
4210  return bAcquire ? ++nDepth : --nDepth;
4211  }
4212 
4213  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4214 
4215  BasePointer _simpl() const override
4216  {
4217  BasePointer fCopy(this->mf0->_simp());
4218  if (fCopy->_kind() == CFUN_K_UMINUS)
4219  { // - - b
4220  return fCopy->_getArg(0);
4221  }
4222  if (fCopy->_kind() == CFUN_K_INFINITY)
4223  {
4224  return std::make_shared<Fmninfinity<T>>();
4225  }
4226  if (fCopy->_kind() == CFUN_K_MNINFINITY)
4227  {
4228  return std::make_shared<Finfinity<T>>();
4229  }
4230  if (fCopy->_kind() == CFUN_K_CONST)
4231  {
4232  return std::make_shared<Fconst<T>>(- fCopy->_value(nullptr));
4233  }
4234  if (fCopy->_kind() == CFUN_K_MINUS)
4235  { // - (a - b) = b - a
4236  return
4237  std::make_shared<Fminus<T>>(fCopy->_getArg(1),
4238  fCopy->_getArg(0));
4239  }
4240  if (fCopy->_kind() == CFUN_K_MULT)
4241  { // - x*y
4242  for (size_t i = 0; i <= 1; ++i)
4243  {
4244  BasePointer fTmp = std::make_shared<Fuminus<T>>(fCopy->_getArg(i));
4245  BasePointer fTmps(fTmp->_simp());
4246  if (!fTmp->_equals(fTmps))
4247  {
4248  return
4249  std::make_shared<Fmult<T>>(fTmps,
4250  fCopy->_getArg(__not(i)))->_simp();
4251  }
4252  }
4253  }
4254  if (fCopy->_kind() == CFUN_K_DIV)
4255  { // - x/y
4256  for (size_t i = 0; i <= 1; ++i)
4257  {
4258  BasePointer fTmp = std::make_shared<Fuminus<T>>(fCopy->_getArg(i));
4259  BasePointer fTmps(fTmp->_simp());
4260  if (!fTmp->_equals(fTmps))
4261  {
4262  BasePointer fTmp(
4263  i ?
4264  std::make_shared<Fdiv<T>>(fCopy->_getArg(__not(i)),
4265  fTmps)
4266  :
4267  std::make_shared<Fdiv<T>>(fTmps,
4268  fCopy->_getArg(__not(i))));
4269  return fTmp->_simp();
4270  }
4271  }
4272  }
4273  return std::make_shared<Fuminus<T>>(fCopy);
4274  }
4275 
4276 public:
4277  Fuminus(const BasePointer& pfSrc)
4278  : UnaryFunction<T>(pfSrc)
4279  {
4280  }
4281 
4282  Fuminus(const std::string& sArg,
4283  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4284  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
4285  {
4286  }
4287 
4288  Fuminus(const std::string& sArg, size_t nF, size_t nL,
4289  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4290  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
4291  {
4292  }
4293 
4294  T _value(const T* pdVars) const override {
4295  return - this->mf0->_value(pdVars);
4296  }
4297 
4298  BasePointer _clone() const override {
4299  return std::make_shared<Fuminus<T>>(this->mf0);
4300  }
4301 
4302  std::string _format(int nPrecision) const override
4303  {
4304  std::ostringstream osBuf;
4305  osBuf << this->_name();
4306  switch (this->mf0->_kind()) {
4307  case CFUN_K_PLUS:
4308  case CFUN_K_MINUS:
4309  case CFUN_K_UMINUS:
4310  osBuf << CFUN_O_SPARENTH << this->mf0->_format(nPrecision) << CFUN_C_PARENTH;
4311  break;
4312  default:
4313  osBuf << this->mf0->_format(nPrecision);
4314  break;
4315  }
4316  return osBuf.str();
4317  }
4318 
4319  BasePointer _deriv(size_t nVarNum) const override
4320  {
4321  return
4322  std::make_shared<Fuminus<T>>(this->mf0->_deriv(nVarNum))->_simp();
4323  }
4324 
4325  const char* _name() const override
4326  {
4327  static const char sz_uminus[] = CFUN_SMINUS;
4328  return sz_uminus;
4329  }
4330 };
4331 
4332 template <typename T>
4333 class Fsign : public UnaryFunction<T>
4334 {
4335 private:
4336  int _kind() const override {
4337  return CFUN_K_SIGN;
4338  }
4339 
4340 protected:
4341  int _depth(bool bAcquire) const override
4342  {
4343  static int nDepth;
4344  return bAcquire ? ++nDepth : --nDepth;
4345  }
4346 
4347  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4348 
4349  BasePointer _simpl() const override
4350  {
4351  BasePointer fCopy(this->mf0->_simp());
4352  if (fCopy->_kind() == CFUN_K_CONST)
4353  {
4354  return std::make_shared<Fconst<T>>(Helper<T>::_value(fCopy.get(), nullptr));
4355  }
4356  return std::make_shared<Fsign<T>>(fCopy);
4357  }
4358 
4359 public:
4360  Fsign(const BasePointer& pfSrc)
4361  : UnaryFunction<T>(pfSrc)
4362  {
4363  }
4364 
4365  Fsign(const std::string& sArg,
4366  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4367  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
4368  {
4369  }
4370 
4371  Fsign(const std::string& sArg, size_t nF, size_t nL,
4372  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4373  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
4374  {
4375  }
4376 
4377  T _value(const T* pdVars) const override {
4378  return Helper<T>::_value(this->mf0.get(), pdVars);
4379  }
4380 
4381  BasePointer _clone() const override {
4382  return std::make_shared<Fsign<T>>(this->mf0);
4383  }
4384 
4385  BasePointer _deriv(size_t) const override
4386  {
4387  return
4388  std::make_shared<Fdelta<T>>(this->mf0,
4389  std::make_shared<Fconst<T>>())->_simp();
4390  }
4391 
4392  const char* _name() const override
4393  {
4394  static const char sz_sign[] = CFUN_SIGN;
4395  return sz_sign;
4396  }
4397 
4398 protected:
4400  template<typename U>
4401  class Helper {
4402  public:
4403  static U _value(const BaseFunction<U>* pfArg, const U* pdVars)
4404  {
4405  const U dV = pfArg->_value(pdVars);
4406  return dV > CFUN_M_ZERO ? CFUN_M_ONE :
4407  (dV < CFUN_M_ZERO ? CFUN_M_MONE : CFUN_M_ZERO);
4408  }
4409  };
4410 
4411  template<typename U>
4412  class Helper<std::complex<U> > {
4413  typedef std::complex<U> UC;
4414  public:
4415  static UC _value(const BaseFunction<UC>* pfArg, const UC* pdVars)
4416  {
4417  const U dV = pfArg->_value(pdVars).real();
4418  return dV > CFUN_M_ZERO ? CFUN_M_ONE :
4419  (dV < CFUN_M_ZERO ? CFUN_M_MONE : CFUN_M_ZERO);
4420  }
4421  };
4423 };
4424 
4425 template <typename T>
4426 class Fabs : public UnaryFunction<T>
4427 {
4428 private:
4429  int _kind() const override {
4430  return CFUN_K_ABS;
4431  }
4432 
4433 protected:
4434  int _depth(bool bAcquire) const override
4435  {
4436  static int nDepth;
4437  return bAcquire ? ++nDepth : --nDepth;
4438  }
4439 
4440  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4441 
4442  BasePointer _simpl() const override
4443  {
4444  BasePointer fCopy(this->mf0->_simp());
4445  if (fCopy->_kind() == CFUN_K_CONST) {
4446  return std::make_shared<Fconst<T>>(cvm::_abs(fCopy->_value(nullptr)));
4447  }
4448  else if (fCopy->_kind() == CFUN_K_ABS) {
4449  return fCopy;
4450  }
4451  return std::make_shared<Fabs<T>>(fCopy);
4452  }
4453 
4454 public:
4455  Fabs(const BasePointer& pfSrc)
4456  : UnaryFunction<T>(pfSrc)
4457  {
4458  }
4459 
4460  Fabs(const std::string& sArg,
4461  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4462  : UnaryFunction<T>(sArg, saVars, saParameters, saMeanings)
4463  {
4464  }
4465 
4466  Fabs(const std::string& sArg, size_t nF, size_t nL,
4467  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4468  : UnaryFunction<T>(sArg, nF, nL, saVars, saParameters, saMeanings)
4469  {
4470  }
4471 
4472  T _value(const T* pdVars) const override {
4473  return cvm::_abs(this->mf0->_value(pdVars));
4474  }
4475 
4476  BasePointer _clone() const override {
4477  return std::make_shared<Fabs<T>>(this->mf0);
4478  }
4479 
4480  BasePointer _deriv(size_t nVarNum) const override
4481  {
4482  return
4483  std::make_shared<Fmult<T>>(std::make_shared<Fsign<T>>(this->mf0),
4484  this->mf0->_deriv(nVarNum))->_simp();
4485  }
4486 
4487  const char* _name() const override
4488  {
4489  static const char sz_abs[] = CFUN_ABS;
4490  return sz_abs;
4491  }
4492 };
4493 
4494 template <typename T>
4495 class Fdelta : public BinaryFunction<T>
4496 {
4497 private:
4498  int _kind() const override {
4499  return CFUN_K_DELTA;
4500  }
4501 
4502 protected:
4503  int _depth(bool bAcquire) const override
4504  {
4505  static int nDepth;
4506  return bAcquire ? ++nDepth : --nDepth;
4507  }
4508 
4509  typedef typename BinaryFunction<T>::BasePointer BasePointer;
4510  typedef shared_ptr_pair<BaseFunction<T>> PointerPair;
4511 
4512  BasePointer _simpl() const override
4513  {
4514  PointerPair fCopy(this->mf0->_simp(), this->mf1->_simp());
4515  if (fCopy[0]->_kind() == CFUN_K_CONST && fCopy[1]->_kind() == CFUN_K_CONST) {
4516  T dM1 = fCopy[0]->_value(nullptr);
4517  T dM2 = fCopy[1]->_value(nullptr);
4518  if (cvm::_abs(dM1 - dM2) <= cvm::cvmMachMin()) {
4519  return std::make_shared<Finfinity<T>>();
4520  }
4521  else {
4522  return std::make_shared<Fconst<T>>();
4523  }
4524  }
4525  return std::make_shared<Fdelta<T>>(fCopy[0], fCopy[1]);
4526  }
4527 
4528 public:
4529  Fdelta(const BasePointer& pfSrc0, const BasePointer& pfSrc1)
4530  : BinaryFunction<T>(pfSrc0, pfSrc1)
4531  {
4532  }
4533 
4534  Fdelta(const std::string& sArg1, const std::string& sArg2,
4535  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4536  : BinaryFunction<T>(sArg1, sArg2, saVars, saParameters, saMeanings)
4537  {
4538  }
4539 
4540  Fdelta(const std::string& sArgs, size_t nF1, size_t nL1, size_t nF2, size_t nL2,
4541  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4542  : BinaryFunction<T>(sArgs, nF1, nL1, nF2, nL2, saVars, saParameters, saMeanings)
4543  {
4544  }
4545 
4546  Fdelta(const std::string& sArg, size_t nFirst, size_t nLast,
4547  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4548  : BinaryFunction<T>(sArg, nFirst, nLast, saVars, saParameters, saMeanings)
4549  {
4550  }
4551 
4552  T _value(const T* pdVars) const override {
4553  return Helper<T>::_value(this->mf0.get(), this->mf1.get(), pdVars);
4554  }
4555 
4556  BasePointer _clone() const override {
4557  return std::make_shared<Fdelta<T>>(this->mf0, this->mf1);
4558  }
4559 
4560  BasePointer _deriv(size_t) const override
4561  {
4562  return
4563  std::make_shared<Fdelta<T>>(this->mf0,
4564  this->mf1)->_simp();
4565  }
4566 
4567  std::string _format(int nPrecision) const override
4568  {
4569  std::ostringstream osBuf;
4570  osBuf << CFUN_DELTA << CFUN_O_PARENTH << this->mf0->_format(nPrecision) << CFUN_SCOMMA <<
4571  this->mf1->_format(nPrecision) << CFUN_C_PARENTH;
4572  return osBuf.str();
4573  }
4574 
4575 protected:
4577  template<typename U>
4578  class Helper {
4579  public:
4580  static U _value(const BaseFunction<U>* pfArg0, const BaseFunction<U>* pfArg1, const U* pdVars)
4581  {
4582  return cvm::_abs(pfArg0->_value(pdVars) - pfArg1->_value(pdVars)) <= basic_cvmMachMin<U>() ?
4583  basic_cvmMachMax<U>() : CFUN_M_ZERO;
4584  }
4585  };
4586 
4587  template<typename U>
4588  class Helper<std::complex<U> > {
4589  typedef std::complex<U> UC;
4590  public:
4591  static UC _value(const BaseFunction<UC>* pfArg0, const BaseFunction<UC>* pfArg1, const UC* pdVars)
4592  {
4593  return cvm::_abs((pfArg0->_value(pdVars) - pfArg1->_value(pdVars)).real()) <= basic_cvmMachMin<U>() ?
4594  basic_cvmMachMax<U>() : CFUN_M_ZERO;
4595  }
4596  };
4598 };
4599 
4600 template <typename T>
4601 class Fvar : public BaseFunction<T>
4602 {
4603 private:
4604  size_t mnVarPos;
4605  std::string msVarName;
4606 
4607  int _kind() const override {
4608  return CFUN_K_VAR;
4609  }
4610 
4611 protected:
4612  int _depth(bool) const override {
4613  return 1;
4614  }
4615 
4616  typedef typename BaseFunction<T>::BasePointer BasePointer;
4617 
4618 
4619  BasePointer _simpl() const override
4620  {
4621  return this->_clone();
4622  }
4623 
4624 public:
4625  Fvar()
4626  : mnVarPos(0),
4627  msVarName()
4628  {
4629  }
4630 
4631  Fvar(const Fvar<T>& rfSrc)
4632  : mnVarPos(rfSrc.mnVarPos),
4633  msVarName(rfSrc.msVarName)
4634  {
4635  }
4636 
4637  Fvar(std::string& sVN, size_t nVP)
4638  : mnVarPos(nVP),
4639  msVarName(sVN)
4640  {
4641  }
4642 
4643  T _value(const T* pdVars) const override
4644  {
4645  if (pdVars == nullptr) {
4646  throw cvmexception(CFUN_NULLPOINTERERROR, "Fvar<T>::_value");
4647  }
4648  return pdVars[mnVarPos];
4649  }
4650 
4651  BasePointer _clone() const override {
4652  return std::make_shared<Fvar<T>>(*this);
4653  }
4654 
4655  std::string _format(int) const override {
4656  return msVarName;
4657  }
4658 
4659  BasePointer _deriv(size_t nVarNum) const override
4660  {
4661  if (mnVarPos == nVarNum) {
4662  return std::make_shared<Fconst<T>>(CFUN_M_ONE);
4663  }
4664  return std::make_shared<Fconst<T>>();
4665  }
4666 
4667  bool _equals(const BasePointer& pfSrc) const override
4668  {
4669  return this->_kind() == pfSrc->_kind() &&
4670  // since kind() is the same we can do this downcasting
4671  mnVarPos == reinterpret_cast<const Fvar<T>*>(pfSrc.get())->mnVarPos &&
4672  msVarName == reinterpret_cast<const Fvar<T>*>(pfSrc.get())->msVarName;
4673  }
4674 
4675  BasePointer _getArg(size_t) const override {
4676  return nullptr;
4677  }
4678 };
4679 
4680 template <typename T>
4681 class Fiif : public UnaryFunction<T>
4682 {
4683 private:
4684  typedef typename UnaryFunction<T>::BasePointer BasePointer;
4685 
4686  int _kind() const override {
4687  return CFUN_K_IIF;
4688  }
4689 
4690  BasePointer mpflt; // if mf0 < 0
4691  BasePointer mpfge; // if mf0 >= 0
4692 
4693 protected:
4694  void TriCtr(const std::string& sBodyCommaBodyCommaBody, size_t nFirst, size_t nLast,
4695  const string_array& saVars,
4696  const string_array& saParameters, const string_array& saMeanings) throw(cvmexception)
4697  {
4698  std::string sF, sLeft, sRight;
4699  if (__separate(sBodyCommaBodyCommaBody, nFirst, nLast, sF, sRight) == 1) {
4700  this->mf0 = FunctionFactory<T>::compile(sF, 0, sF.length(), saVars, saParameters, saMeanings);
4701  if (__separate(sRight, 0, sRight.length(), sLeft, sRight) == 1) {
4702  mpflt = FunctionFactory<T>::compile(sLeft, 0, sLeft.length(), saVars, saParameters, saMeanings);
4703  mpfge = FunctionFactory<T>::compile(sRight, 0, sRight.length(), saVars, saParameters, saMeanings);
4704  return;
4705  }
4706  }
4707  throw cvmexception(CFUN_PARSEERROR, sBodyCommaBodyCommaBody.c_str(), __format_vars(saVars).c_str());
4708  }
4709 
4710  int _depth(bool bAcquire) const override
4711  {
4712  static int nDepth;
4713  return bAcquire ? ++nDepth : --nDepth;
4714  }
4715 
4716  BasePointer _simpl() const override
4717  {
4718  return std::make_shared<Fiif<T>>(this->mf0->_simp(), this->mpflt->_simp(), this->mpfge->_simp());
4719  }
4720 
4721 public:
4722  Fiif(const BasePointer& rfSrc, const BasePointer& rfLT, const BasePointer& rfGE)
4723  : UnaryFunction<T>(rfSrc),
4724  mpflt(rfLT),
4725  mpfge(rfGE)
4726  {
4727  }
4728 
4729  Fiif(const std::string& sBody,
4730  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4731  : mpflt(nullptr),
4732  mpfge(nullptr)
4733  {
4734  TriCtr(sBody, 0, sBody.length(), saVars, saParameters, saMeanings);
4735  }
4736 
4737  Fiif(const std::string& sBody, size_t nFirst, size_t nLast,
4738  const string_array& saVars, const string_array& saParameters, const string_array& saMeanings)
4739  : mpflt(nullptr),
4740  mpfge(nullptr)
4741  {
4742  TriCtr(sBody, nFirst, nLast, saVars, saParameters, saMeanings);
4743  }
4744 
4745  T _value(const T* pdVars) const override {
4746  return Helper<T>::left(this->mf0.get(), pdVars) ? this->mpflt->_value(pdVars) :
4747  this->mpfge->_value(pdVars);
4748  }
4749 
4750  BasePointer _clone() const override {
4751  return std::make_shared<Fiif<T>>(*this);
4752  }
4753 
4754  BasePointer _deriv(size_t nVarNum) const override
4755  {
4756  return
4757  std::make_shared<Fiif<T>>(this->mf0, this->mpflt->_deriv(nVarNum), this->mpfge->_deriv(nVarNum));
4758  }
4759 
4760  std::string _format(int nPrecision) const override
4761  {
4762  std::ostringstream osBuf;
4763  osBuf << this->_name() << CFUN_O_PARENTH << this->mf0->_format(nPrecision) << CFUN_SCOMMA <<
4764  this->mpflt->_format(nPrecision) << CFUN_SCOMMA <<
4765  this->mpfge->_format(nPrecision) << CFUN_C_PARENTH;
4766  return osBuf.str();
4767  }
4768 
4769  const char* _name() const override
4770  {
4771  static const char sz_iif[] = CFUN_IIF;
4772  return sz_iif;
4773  }
4774 
4775 protected:
4777  template<typename U>
4778  class Helper {
4779  public:
4780  static bool left(const BaseFunction<U>* pfArg0, const U* pdVars)
4781  {
4782  return pfArg0->_value(pdVars) < CFUN_M_ZERO;
4783  }
4784  };
4785 
4786  template<typename U>
4787  class Helper<std::complex<U> > {
4788  typedef std::complex<U> UC;
4789  public:
4790  static bool left(const BaseFunction<UC>* pfArg0, const UC* pdVars)
4791  {
4792  return pfArg0->_value(pdVars).real() < CFUN_M_ZERO;
4793  }
4794  };
4796 };
4797 
4799 
4800 
4918 template <typename T>
4920 {
4921 public:
4923 
4924 protected:
4925  mutable string_array mvars;
4927 
4929  const string_array& _check_vars(const string_array& saVars) const throw(cvmexception)
4930  {
4931  if (this->vars_num() > 0 && saVars.size() > 0 && !__arrays_equal(mvars, saVars)) {
4932  throw cvmexception(CFUN_VARSDONTMATCH, __format_vars(mvars).c_str(), __format_vars(saVars).c_str());
4933  }
4934  return this->vars_num() > 0 ? mvars : saVars; // here we cover cases like '5+x'
4935  }
4936 
4937  // protected utility constructor
4938  basic_function(const string_array& saVars, const BasePointer& pf)
4939  : mvars(saVars),
4940  mp(pf)
4941  {
4942  }
4943 
4944  basic_function(string_array&& saVars, BasePointer&& pf)
4945  : mvars(std::move(saVars)),
4946  mp(std::move(pf))
4947  {
4948  }
4950 
4951 public:
4976  : mvars(),
4977  mp(std::make_shared<Fconst<T>>())
4978  {
4979  }
4980 
5008  explicit basic_function(const string_array& saVars)
5009  : mvars(saVars),
5010  mp(std::make_shared<Fconst<T>>())
5011  {
5012  }
5013 
5041  explicit basic_function(const T& dConst)
5042  : mvars(),
5043  mp(std::make_shared<Fconst<T>>(dConst))
5044  {
5045  }
5046 
5071  : mvars(rf.mvars),
5072  mp(rf.mp)
5073  {
5074  }
5075 
5080  : mvars(std::move(rf.mvars)),
5081  mp(std::move(rf.mp))
5082  {
5083  }
5084 
5121  explicit basic_function(const std::string& sInput)
5122  : mvars(),
5123  mp()
5124  {
5125  string_array saParameters, saMeanings;
5126  size_t nAF = sInput.find(CFUN_O_BRACE, 0);
5127  size_t nAL = sInput.find(CFUN_C_BRACE, 0);
5128  if (nAL != CFUN_NOT_FOUND && nAL > nAF) {
5129  __parse_vars(sInput, nAF + 1, nAL, mvars);
5130  }
5131  mp = FunctionFactory<T>::compile(sInput, nAL + 1, sInput.length(), mvars, saParameters, saMeanings);
5132  }
5133 
5174  basic_function(const string_array& saVars, const std::string& sBody)
5175  : mvars(saVars),
5176  mp()
5177  {
5178  string_array saParameters, saMeanings;
5179  mp = FunctionFactory<T>::compile(sBody, 0, sBody.length(), mvars, saParameters, saMeanings);
5180  }
5181 
5228  basic_function(const string_array& saVars, const std::string& sBody,
5229  const string_array& saParameters, const string_array& saMeanings)
5230  : mvars(saVars),
5231  mp(FunctionFactory<T>::compile(sBody, 0, sBody.length(), mvars, saParameters, saMeanings))
5232  {
5233  }
5234 
5239  {
5240  }
5241 
5258  const string_array& vars() const {
5259  return mvars;
5260  }
5261 
5277  size_t vars_num() const {
5278  return mvars.size();
5279  }
5280 
5311  T value(const T* pd) const {
5312  return mp->_value(pd);
5313  }
5314 
5315 
5346  T operator () (const T* pd) const {
5347  return mp->_value(pd);
5348  }
5349 
5379  T operator () (const T& d) const {
5380  return mp->_value(&d);
5381  }
5382 
5412  T operator () (const T& d1, const T& d2) const
5413  {
5414  T dVals[2];
5415  dVals[0] = d1;
5416  dVals[1] = d2;
5417  return mp->_value(dVals);
5418  }
5419 
5445  T operator () (const T& d1, const T& d2, const T& d3) const
5446  {
5447  T dVals[3];
5448  dVals[0] = d1;
5449  dVals[1] = d2;
5450  dVals[2] = d3;
5451  return mp->_value(dVals);
5452  }
5453 
5491  T operator () () const
5492  {
5493  static const T dZero = T();
5494  return mp->_value(&dZero);
5495  }
5496 
5530  std::string format(int nPrecision = 0) const {
5531  return mp->_format(nPrecision);
5532  }
5533 
5568  std::string vformat(int nPrecision = 0) const
5569  {
5570  std::stringstream stream;
5571  std::string vars = __format_vars(this->mvars, false);
5572  if (vars.size() > 0) {
5573  stream << vars << CFUN_SSPACE;
5574  }
5575  stream << mp->_format(nPrecision);
5576  return stream.str();
5577  }
5578 
5606  bool operator == (const basic_function& rf) const {
5607  return vars_num() == rf.vars_num() && mp->_equals(rf.mp);
5608  }
5609 
5637  bool operator != (const basic_function& rf) const {
5638  return !operator == (rf);
5639  }
5640 
5688  basic_function drv(size_t nVarNum = 0) const {
5689  return basic_function(mvars, mp->_deriv(nVarNum));
5690  }
5691 
5715  {
5716  mp = mp->_simp();
5717  return *this;
5718  }
5719 
5747  {
5748  if (mp != rfSrc.mp) {
5749  // we don't check vars here, we just override...
5750  mvars = rfSrc.mvars;
5751  mp = rfSrc.mp;
5752  }
5753  return *this;
5754  }
5755 
5760  {
5761  if (mp != rfSrc.mp) {
5762  // we don't check vars here, we just override...
5763  mvars = std::move(rfSrc.mvars);
5764  mp = std::move(rfSrc.mp);
5765  }
5766  return *this;
5767  }
5768 
5798  basic_function& operator = (const T& rdSrc)
5799  {
5800  mp = std::make_shared<Fconst<T>>(rdSrc);
5801  return *this;
5802  }
5803 
5829  return basic_function(mvars, std::make_shared<Fuminus<T>>(mp));
5830  }
5831 
5863  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fplus<T>>(mp, rf.mp));
5864  }
5865 
5897  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fminus<T>>(mp, rf.mp));
5898  }
5899 
5935  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fmult<T>>(mp, rf.mp));
5936  }
5937 
5973  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fdiv<T>>(mp, rf.mp));
5974  }
5975 
6007  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fpower<T>>(mp, rf.mp));
6008  }
6009 
6044  {
6045  mvars = this->_check_vars(rf.mvars);
6046  mp = std::make_shared<Fplus<T>>(mp, rf.mp);
6047  return *this;
6048  }
6049 
6084  {
6085  mvars = this->_check_vars(rf.mvars);
6086  mp = std::make_shared<Fminus<T>>(mp, rf.mp);
6087  return *this;
6088  }
6089 
6128  {
6129  mvars = this->_check_vars(rf.mvars);
6130  mp = std::make_shared<Fmult<T>>(mp, rf.mp);
6131  return *this;
6132  }
6133 
6172  {
6173  mvars = this->_check_vars(rf.mvars);
6174  mp = std::make_shared<Fdiv<T>>(mp, rf.mp);
6175  return *this;
6176  }
6177 
6200  basic_function operator + (const T& d) const throw(cvmexception) {
6201  return basic_function(mvars, std::make_shared<Fplus<T>>(mp, std::make_shared<Fconst<T>>(d)));
6202  }
6203 
6227  basic_function operator - (const T& d) const throw(cvmexception) {
6228  return basic_function(mvars, std::make_shared<Fminus<T>>(mp, std::make_shared<Fconst<T>>(d)));
6229  }
6230 
6258  basic_function operator *(const T& d) const throw(cvmexception) {
6259  return basic_function(mvars, std::make_shared<Fmult<T>>(mp, std::make_shared<Fconst<T>>(d)));
6260  }
6261 
6288  basic_function operator / (const T& d) const throw(cvmexception) {
6289  return basic_function(mvars, std::make_shared<Fdiv<T>>(mp, std::make_shared<Fconst<T>>(d)));
6290  }
6291 
6314  basic_function operator ^(const T& d) const throw(cvmexception) {
6315  return basic_function(mvars, std::make_shared<Fpower<T>>(mp, std::make_shared<Fconst<T>>(d)));
6316  }
6317 
6344  {
6345  mp = std::make_shared<Fplus<T>>(mp, std::make_shared<Fconst<T>>(d));
6346  return *this;
6347  }
6348 
6375  {
6376  mp = std::make_shared<Fminus<T>>(mp, std::make_shared<Fconst<T>>(d));
6377  return *this;
6378  }
6379 
6410  {
6411  mp = std::make_shared<Fmult<T>>(mp, std::make_shared<Fconst<T>>(d));
6412  return *this;
6413  }
6414 
6445  {
6446  mp = std::make_shared<Fdiv<T>>(mp, std::make_shared<Fconst<T>>(d));
6447  return *this;
6448  }
6449 
6476  {
6477  mp = std::make_shared<Fpower<T>>(mp, std::make_shared<Fconst<T>>(d));
6478  return *this;
6479  }
6480 
6540  basic_function sat(const basic_function& rf) const throw(cvmexception) {
6541  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fsat<T>>(mp, rf.mp));
6542  }
6543 
6571  return basic_function(mvars, std::make_shared<Fexp<T>>(mp));
6572  }
6573 
6602  return basic_function(mvars, std::make_shared<Fsqrt<T>>(mp));
6603  }
6604 
6633  return basic_function(mvars, std::make_shared<Flog<T>>(mp));
6634  }
6635 
6664  return basic_function(mvars, std::make_shared<Flog10<T>>(mp));
6665  }
6666 
6695  return basic_function(mvars, std::make_shared<Fsin<T>>(mp));
6696  }
6697 
6726  return basic_function(mvars, std::make_shared<Fcos<T>>(mp));
6727  }
6728 
6756  return basic_function(mvars, std::make_shared<Ftan<T>>(mp));
6757  }
6758 
6786  return basic_function(mvars, std::make_shared<Fasin<T>>(mp));
6787  }
6788 
6816  return basic_function(mvars, std::make_shared<Facos<T>>(mp));
6817  }
6818 
6847  return basic_function(mvars, std::make_shared<Fatan<T>>(mp));
6848  }
6849 
6878  return basic_function(mvars, std::make_shared<Fsinh<T>>(mp));
6879  }
6880 
6909  return basic_function(mvars, std::make_shared<Fcosh<T>>(mp));
6910  }
6911 
6940  return basic_function(mvars, std::make_shared<Ftanh<T>>(mp));
6941  }
6942 
6971  return basic_function(mvars, std::make_shared<Fsinint<T>>(mp));
6972  }
6973 
7002  return basic_function(mvars, std::make_shared<Fcosint<T>>(mp));
7003  }
7004 
7053  return basic_function(mvars, std::make_shared<Fsign<T>>(mp));
7054  }
7055 
7092  return basic_function(mvars, std::make_shared<Fabs<T>>(mp));
7093  }
7094 
7150  return basic_function(this->_check_vars(rf.mvars), std::make_shared<Fdelta<T>>(mp, rf.mp));
7151  }
7152 
7212  const basic_function& rfNotNeg) const throw(cvmexception)
7213  {
7214  const string_array& saVarsT = this->_check_vars(rfNeg.mvars);
7215  const string_array& saVarsF = this->_check_vars(rfNotNeg.mvars);
7216  const string_array& saVars = saVarsT.size() > saVarsF.size() ? saVarsT : saVarsF;
7217  return basic_function(saVars, std::make_shared<Fiif<T>>(mp, rfNeg.mp, rfNotNeg.mp));
7218  }
7219 
7243  friend basic_function<T> operator + (const T& d, const basic_function<T>& rf) {
7244  return rf + d;
7245  }
7246 
7270  friend basic_function<T> operator - (const T& d, const basic_function<T>& rf) {
7271  return basic_function(rf.mvars, std::make_shared<Fminus<T>>(std::make_shared<Fconst<T>>(d), rf.mp));
7272  }
7273 
7301  friend basic_function<T> operator *(const T& d, const basic_function<T>& rf) {
7302  return rf * d;
7303  }
7304 
7332  friend basic_function<T> operator / (const T& d, const basic_function<T>& rf) {
7333  return basic_function(rf.mvars, std::make_shared<Fdiv<T>>(std::make_shared<Fconst<T>>(d), rf.mp));
7334  }
7335 
7359  friend basic_function<T> operator ^(const T& d, const basic_function<T>& rf) {
7360  return basic_function(rf.mvars, std::make_shared<Fpower<T>>(std::make_shared<Fconst<T>>(d), rf.mp));
7361  }
7362 
7388  friend std::ostream& operator <<(std::ostream& os, const basic_function& rf)
7389  {
7390  std::string vars = __format_vars(rf.mvars, false);
7391  if (vars.size() > 0) {
7392  os << vars << CFUN_SSPACE;
7393  }
7394  os << rf.format(0);
7395  return os;
7396  }
7397 
7399  // sets caller to be equal to scalar product of fa1 and fa2
7400  basic_function& _scalar_product(size_t nSize,
7401  const basic_function* fa1, size_t incr1,
7402  const basic_function* fa2, size_t incr2) throw(cvmexception)
7403  {
7404  const string_array& saVars1 = this->_check_vars(fa1->vars());
7405  const string_array& saVars2 = this->_check_vars(fa2->vars());
7406  const string_array& saVars = saVars1.size() > saVars2.size() ? saVars1 : saVars2;
7407 
7408  mvars = saVars;
7409  mp = std::make_shared<Fconst<T>>();
7410 
7411  for (size_t i = 0; i < nSize; ++i, fa1 += incr1, fa2 += incr2)
7412  {
7413  *this += (*fa1) * (*fa2);
7414  }
7415  return this->simp();
7416  }
7418 };
7419 
7420 
7422 template<typename BaseFunction>
7423 inline void _copy(size_t nSize,
7424  const BaseFunction* faFrom, size_t incrFrom,
7425  BaseFunction* faTo, size_t incrTo)
7426 {
7427  for (size_t i = 0; i < nSize; ++i, faFrom += incrFrom, faTo += incrTo) {
7428  *faTo = *faFrom;
7429  }
7430 }
7432 
7433 
7442 template<typename T>
7443 class FArray
7444 {
7445 protected:
7447 
7448  std::vector<BaseFunction> mv;
7449 
7451  void _assign(const FArray& a)
7452  {
7453  for (size_t i = 0; i < mv.size(); ++i) {
7454  mv.at(i) = a.mv.at(i);
7455  }
7456  }
7458 
7459 public:
7466  : mv()
7467  {
7468  }
7469 
7476  explicit FArray(size_t nSize)
7477  : mv(nSize)
7478  {
7479  }
7480 
7487  FArray(const FArray& a)
7488  : mv(a.size())
7489  {
7490  this->_assign(a);
7491  }
7492 
7497  : mv(std::move(a.mv))
7498  {
7499  }
7500 
7509  explicit FArray(const string_array& saInput)
7510  : mv(saInput.size())
7511  {
7512  for (size_t i = 0; i < mv.size(); ++i) {
7513  mv.at(i) = BaseFunction(saInput[i]);
7514  }
7515  }
7516 
7528  FArray(const string_array& saVars, const string_array& saBodies,
7529  const string_array& saParameters, const string_array& saMeanings)
7530  : mv(saBodies.size())
7531  {
7532  for (size_t i = 0; i < mv.size(); ++i) {
7533  mv.at(i) = BaseFunction(saVars, saBodies[i], saParameters, saMeanings);
7534  }
7535  }
7536 
7540  virtual ~FArray()
7541  {
7542  }
7543 
7551  std::vector<BaseFunction>& impl() {
7552  return mv;
7553  }
7554 
7562  const std::vector<BaseFunction>& impl() const {
7563  return mv;
7564  }
7565 
7575  size_t size() const {
7576  return mv.size();
7577  }
7578 
7587  const BaseFunction& operator [] (size_t n) const {
7588  return mv.at(n);
7589  }
7590 
7600  return mv.at(n);
7601  }
7602 
7635  void value(T* pv) const {
7636  value(nullptr, pv);
7637  }
7638 
7673  void value(T d, T* pv) const {
7674  value(&d, pv);
7675  }
7676 
7712  void value(T d1, T d2, T* pv) const {
7713  T d[2];
7714  d[0] = d1;
7715  d[1] = d2;
7716  value(d, pv);
7717  }
7718 
7755  void value(T d1, T d2, T d3, T* pv) const {
7756  T d[3];
7757  d[0] = d1;
7758  d[1] = d2;
7759  d[2] = d3;
7760  value(d, pv);
7761  }
7762 
7799  void value(const T* pd, T* pv) const
7800  {
7801  for (size_t i = 0; i < mv.size(); ++i) {
7802  pv[i] = mv.at(i).value(pd);
7803  }
7804  }
7805 
7807 protected:
7808  void _drv(const FArray& a, size_t nVarNum)
7809  {
7810  for (size_t i = 0; i < mv.size(); ++i) {
7811  mv.at(i) = a.mv.at(i).drv(nVarNum);
7812  }
7813  }
7814 
7815  void _simp()
7816  {
7817  for (size_t i = 0; i < mv.size(); ++i) {
7818  mv.at(i).simp();
7819  }
7820  }
7821 
7822  bool _equals(const FArray& a) const
7823  {
7824  bool bResult = true;
7825  if (mv.size() != a.size()) {
7826  bResult = false;
7827  }
7828  else
7829  for (size_t i = 0; i < mv.size(); ++i) {
7830  if (mv.at(i) != a.mv.at(i)) {
7831  bResult = false;
7832  break;
7833  }
7834  }
7835  return bResult;
7836  }
7837 
7838  void _add(const FArray& a)
7839  {
7840  for (size_t i = 0; i < mv.size(); ++i) {
7841  mv.at(i) += a.mv.at(i);
7842  }
7843  }
7844 
7845  void _subtract(const FArray& a)
7846  {
7847  for (size_t i = 0; i < mv.size(); ++i) {
7848  mv.at(i) -= a.mv.at(i);
7849  }
7850  }
7851 
7852  void _add(const FArray& a1, const FArray& a2)
7853  {
7854  for (size_t i = 0; i < mv.size(); ++i) {
7855  mv.at(i) = a1.mv.at(i) + a2.mv.at(i);
7856  }
7857  }
7858 
7859  void _subtract(const FArray& a1, const FArray& a2)
7860  {
7861  for (size_t i = 0; i < mv.size(); ++i) {
7862  mv.at(i) = a1.mv.at(i) - a2.mv.at(i);
7863  }
7864  }
7865 
7866  void _mult(const BaseFunction& f)
7867  {
7868  for (size_t i = 0; i < mv.size(); ++i) {
7869  mv.at(i) *= f;
7870  }
7871  }
7872 
7873  void _div(const BaseFunction& f)
7874  {
7875  for (size_t i = 0; i < mv.size(); ++i) {
7876  mv.at(i) /= f;
7877  }
7878  }
7879 
7880  void _mult(const FArray& a, const BaseFunction& f)
7881  {
7882  for (size_t i = 0; i < mv.size(); ++i) {
7883  mv.at(i) = a.mv.at(i) * f;
7884  }
7885  }
7886 
7887  void _div(const FArray& a, const BaseFunction& f)
7888  {
7889  for (size_t i = 0; i < mv.size(); ++i) {
7890  mv.at(i) = a.mv.at(i) / f;
7891  }
7892  }
7893 
7894  void _mult(const T& t)
7895  {
7896  for (size_t i = 0; i < mv.size(); ++i) {
7897  mv.at(i) *= t;
7898  }
7899  }
7900 
7901  void _div(const T& t)
7902  {
7903  for (size_t i = 0; i < mv.size(); ++i) {
7904  mv.at(i) /= t;
7905  }
7906  }
7907 
7908  void _mult(const FArray& a, const T& t)
7909  {
7910  for (size_t i = 0; i < mv.size(); ++i) {
7911  mv.at(i) = a.mv.at(i) * t;
7912  }
7913  }
7914 
7915  void _div(const FArray& a, const T& t)
7916  {
7917  for (size_t i = 0; i < mv.size(); ++i) {
7918  mv.at(i) = a.mv.at(i) / t;
7919  }
7920  }
7922 };
7923 
7924 
7925 template<typename T> class basic_fvector;
7926 template<typename T> class basic_fmatrix;
7927 
7928 
7938 template<typename T>
7939 class basic_fvector : public FArray<T>
7940 {
7941  friend class basic_fmatrix<T>; // for _mult
7942 
7943 protected:
7946 
7948  void _check_size(size_t size) const throw(cvmexception)
7949  {
7950  _check_ne(CVM_SIZESMISMATCH, size, this->size());
7951  }
7953 
7954 public:
7961  : BaseFArray()
7962  {
7963  }
7964 
7984  explicit basic_fvector(size_t nSize)
7985  : BaseFArray(nSize)
7986  {
7987  }
7988 
8025  explicit basic_fvector(const string_array& saInput)
8026  : BaseFArray(saInput)
8027  {
8028  }
8029 
8075  basic_fvector(const string_array& saVars, const string_array& saBodies,
8076  const string_array& saParameters, const string_array& saMeanings)
8077  : BaseFArray(saVars, saBodies, saParameters, saMeanings)
8078  {
8079  }
8080 
8088  : BaseFArray(fv)
8089  {
8090  }
8091 
8096  : BaseFArray(std::move(fv))
8097  {
8098  }
8099 
8131  {
8132  this->_check_size(fv.size());
8133  this->_assign(fv);
8134  return *this;
8135  }
8136 
8141  {
8142  this->_check_size(fv.size());
8143  this->mv = std::move(fv.mv);
8144  return *this;
8145  }
8146 
8180  bool operator == (const basic_fvector& fv) const {
8181  return this->_equals(fv);
8182  }
8183 
8217  bool operator != (const basic_fvector& fv) const {
8218  return !this->_equals(fv);
8219  }
8220 
8251  {
8252  this->mv.resize(fv.size());
8253  this->_assign(fv);
8254  return *this;
8255  }
8256 
8285  basic_fvector drv(size_t nVarNum) const
8286  {
8287  basic_fvector vRet(this->size());
8288  vRet._drv(*this, nVarNum);
8289  return vRet;
8290  }
8291 
8315  {
8316  this->_simp();
8317  return *this;
8318  }
8319 
8355  {
8356  this->_check_size(fv.size());
8357  basic_fvector vRet(this->size());
8358  vRet._add(*this, fv);
8359  return vRet;
8360  }
8361 
8397  {
8398  this->_check_size(fv.size());
8399  basic_fvector vRet(this->size());
8400  vRet._subtract(*this, fv);
8401  return vRet;
8402  }
8403 
8442  {
8443  this->_check_size(fv.size());
8444  this->_add(fv);
8445  return *this;
8446  }
8447 
8486  {
8487  this->_check_size(fv.size());
8488  this->_subtract(fv);
8489  return *this;
8490  }
8491 
8527  {
8528  basic_fvector vRet(this->size());
8529  vRet.BaseFArray::_mult(*this, f);
8530  return vRet;
8531  }
8532 
8568  {
8569  basic_fvector vRet(this->size());
8570  vRet._div(*this, f);
8571  return vRet;
8572  }
8573 
8606  basic_fvector operator *(const T& d) const
8607  {
8608  basic_fvector vRet(this->size());
8609  vRet.BaseFArray::_mult(*this, d);
8610  return vRet;
8611  }
8612 
8645  basic_fvector operator / (const T& d) const
8646  {
8647  basic_fvector vRet(this->size());
8648  vRet._div(*this, d);
8649  return vRet;
8650  }
8651 
8692  {
8693  this->BaseFArray::_mult(f);
8694  return *this;
8695  }
8696 
8737  {
8738  this->BaseFArray::_div(f);
8739  return *this;
8740  }
8741 
8781  {
8782  this->BaseFArray::_mult(d);
8783  return *this;
8784  }
8785 
8825  {
8826  this->BaseFArray::_div(d);
8827  return *this;
8828  }
8829 
8867  {
8868  this->_check_size(fv.size());
8869  BaseFunction fRet;
8870  fRet._scalar_product(this->mv.size(), &this->mv.at(0), 1, &fv.mv.at(0), 1);
8871  return fRet;
8872  }
8873 
8920  {
8921  this->_check_size(fm.msize());
8922  basic_fvector vRet(fm.nsize());
8923  vRet._mult(*this, fm);
8924  return vRet;
8925  }
8926 
8979  {
8980  fv._check_size(fm.msize());
8981  this->_check_size(fm.nsize());
8982  return this->_mult(fv, fm);
8983  }
8984 
9037  {
9038  fv._check_size(fm.nsize());
9039  this->_check_size(fm.msize());
9040  return this->_mult(fm, fv);
9041  }
9042 
9103  basic_fmatrix<T> jacobian(size_t nfrom = 0, size_t vars = 0) const
9104  {
9105  const size_t m = this->size();
9106  if (m <= 0) {
9107  return basic_fmatrix<T>();
9108  }
9109  const size_t sz = this->mv.at(0).vars().size();
9110  _check_ge(CVM_INDEX_GE, nfrom, sz);
9111 
9112  const size_t n = vars > 0 ? vars : sz - nfrom;
9113  _check_gt(CVM_INDEX_GT, nfrom + n, sz);
9114 
9115  basic_fmatrix<T> fmj(m, n);
9116  this->_jacobi(fmj, nfrom);
9117  return fmj;
9118  }
9119 
9190  void jacobian(basic_fmatrix<T>& fmj, size_t nfrom = 0, size_t vars = 0) const
9191  {
9192  const size_t m = this->size();
9193  _check_ne(CVM_SIZESMISMATCH, m, fmj.msize());
9194  if (m > 0) {
9195  const size_t sz = this->mv.at(0).vars().size();
9196  _check_ge(CVM_INDEX_GE, nfrom, sz);
9197  const size_t n = vars > 0 ? vars : sz - nfrom;
9198  _check_gt(CVM_INDEX_GT, nfrom + n, sz);
9199  _check_ne(CVM_SIZESMISMATCH, n, fmj.nsize());
9200  this->_jacobi(fmj, nfrom);
9201  }
9202  }
9203 
9231  friend std::ostream& operator <<(std::ostream& os, const basic_fvector<T>& fv)
9232  {
9233  for (size_t i = 0; i < fv.size(); ++i) {
9234  os << fv.mv.at(i) << " ";
9235  }
9236  os << std::endl;
9237  return os;
9238  }
9239 
9240 protected:
9242  // internal version, it doesn't verify anything
9243  basic_fvector& _mult(const basic_fvector& fv, const basic_fmatrix<T>& fm) throw(cvmexception)
9244  {
9245  for (size_t i = 0; i < fm.nsize(); ++i) {
9246  this->mv.at(i)._scalar_product(fv.size(), &fv.mv.at(0), 1, &fm.mv.at(fm.msize() * i), 1);
9247  }
9248  return *this;
9249  }
9250  // internal version, it doesn't verify anything
9251  basic_fvector& _mult(const basic_fmatrix<T>& fm, const basic_fvector& fv) throw(cvmexception)
9252  {
9253  for (size_t i = 0; i < fm.msize(); ++i) {
9254  this->mv.at(i)._scalar_product(fm.nsize(), &fm.mv.at(i), fm.msize(), &fv.mv.at(0), 1);
9255  }
9256  return *this;
9257  }
9258  // internal version, it doesn't verify anything
9259  // starts from nfrom-th variable (0-based)
9260  void _jacobi(basic_fmatrix<T>& fmj, size_t nfrom) const
9261  {
9262  for (size_t i = 0; i < fmj.msize(); ++i) {
9263  for (size_t j = 0; j < fmj.nsize(); ++j) {
9264  fmj.mv.at(fmj.msize() * j + i) = this->mv.at(i).drv(j + nfrom);
9265  }
9266  }
9267  }
9269 };
9270 
9271 
9278 class rfvector : public basic_fvector<treal>
9279 {
9280 protected:
9282 
9283 public:
9290  : BaseFVector()
9291  {
9292  }
9293 
9313  explicit rfvector(size_t nSize)
9314  : BaseFVector(nSize)
9315  {
9316  }
9317 
9354  explicit rfvector(const string_array& saInput)
9355  : BaseFVector(saInput)
9356  {
9357  }
9358 
9404  rfvector(const string_array& saVars, const string_array& saBodies,
9405  const string_array& saParameters, const string_array& saMeanings)
9406  : BaseFVector(saVars, saBodies, saParameters, saMeanings)
9407  {
9408  }
9409 
9417  : BaseFVector(fv)
9418  {
9419  }
9420 
9425  : BaseFVector(std::move(fv))
9426  {
9427  }
9428 
9458  rvector ret((tint)this->size());
9459  this->value(ret);
9460  return ret;
9461  }
9462 
9494  rvector ret((tint)this->size());
9495  this->value(d, ret);
9496  return ret;
9497  }
9498 
9531  rvector ret((tint)this->size());
9532  this->value(d1, d2, ret);
9533  return ret;
9534  }
9535 
9568  rvector operator () (treal d1, treal d2, treal d3) const {
9569  rvector ret((tint)this->size());
9570  this->value(d1, d2, d3, ret);
9571  return ret;
9572  }
9573 
9609  rvector operator () (const treal* pd) const {
9610  rvector ret((tint)this->size());
9611  this->value(pd, ret);
9612  return ret;
9613  }
9614 };
9615 
9616 
9623 class cfvector : public basic_fvector<tcomplex>
9624 {
9625 protected:
9627 
9628 public:
9635  : BaseFVector()
9636  {
9637  }
9638 
9658  explicit cfvector(size_t nSize)
9659  : BaseFVector(nSize)
9660  {
9661  }
9662 
9699  explicit cfvector(const string_array& saInput)
9700  : BaseFVector(saInput)
9701  {
9702  }
9703 
9749  cfvector(const string_array& saVars, const string_array& saBodies,
9750  const string_array& saParameters, const string_array& saMeanings)
9751  : BaseFVector(saVars, saBodies, saParameters, saMeanings)
9752  {
9753  }
9754 
9762  : BaseFVector(fv)
9763  {
9764  }
9765 
9770  : BaseFVector(std::move(fv))
9771  {
9772  }
9773 
9802  cvector ret((tint)this->size());
9803  this->value(ret);
9804  return ret;
9805  }
9806 
9838  cvector ret((tint)this->size());
9839  this->value(d, ret);
9840  return ret;
9841  }
9842 
9875  cvector ret((tint)this->size());
9876  this->value(d1, d2, ret);
9877  return ret;
9878  }
9879 
9913  cvector ret((tint)this->size());
9914  this->value(d1, d2, d3, ret);
9915  return ret;
9916  }
9917 
9953  cvector operator () (const tcomplex* pd) const {
9954  cvector ret((tint)this->size());
9955  this->value(pd, ret);
9956  return ret;
9957  }
9958 
9959 };
9960 
9961 
9971 template<typename T>
9972 class basic_fmatrix : public FArray<T>
9973 {
9974  friend class basic_fvector<T>; // _mult
9975 
9976 protected:
9979 
9980  size_t mM;
9981  size_t mN;
9982 
9984  void _check_sizes(const basic_fmatrix& fm) const throw(cvmexception)
9985  {
9986  _check_ne(CVM_SIZESMISMATCH, fm.msize(), this->msize());
9987  _check_ne(CVM_SIZESMISMATCH, fm.nsize(), this->nsize());
9988  }
9989  void _check_sizes() const throw(cvmexception)
9990  {
9991  static const size_t ZERO(0);
9992  _check_le(CVM_WRONGSIZE_LE, this->msize(), ZERO);
9993  _check_le(CVM_WRONGSIZE_LE, this->nsize(), ZERO);
9994  _check_ne(CVM_SIZESMISMATCH, mM * mN, this->size());
9995  }
9997 
9998 public:
10005  : BaseFArray(),
10006  mM(0),
10007  mN(0)
10008  {
10009  }
10010 
10033  basic_fmatrix(size_t m, size_t n)
10034  : BaseFArray(m * n),
10035  mM(m),
10036  mN(n)
10037  {
10038  this->_check_sizes();
10039  }
10040 
10075  basic_fmatrix(size_t m, size_t n, const string_array& saInput)
10076  : BaseFArray(saInput),
10077  mM(m),
10078  mN(n)
10079  {
10080  this->_check_sizes();
10081  }
10082 
10129  basic_fmatrix(size_t m, size_t n, const string_array& saVars, const string_array& saBodies,
10130  const string_array& saParameters, const string_array& saMeanings)
10131  : BaseFArray(saVars, saBodies, saParameters, saMeanings), mM(m), mN(n)
10132  {
10133  this->_check_sizes();
10134  }
10135 
10143  : BaseFArray(fm), mM(fm.msize()), mN(fm.nsize())
10144  {
10145  }
10146 
10151  : BaseFArray(std::move(fm)), mM(fm.msize()), mN(fm.nsize())
10152  {
10153  }
10154 
10174  size_t msize() const {
10175  return mM;
10176  }
10177 
10197  size_t nsize() const {
10198  return mN;
10199  }
10200 
10201  // no destructor here because non-virtual std::vector::~vector does the job
10202 
10234  basic_fmatrix& operator = (const basic_fmatrix& fm) throw(cvmexception)
10235  {
10236  this->_check_sizes(fm);
10237  this->_assign(fm);
10238  return *this;
10239  }
10240 
10244  basic_fmatrix& operator = (basic_fmatrix&& fm) throw(cvmexception)
10245  {
10246  this->_check_sizes(fm);
10247  this->mp = std::move(fm.mv);
10248  return *this;
10249  }
10250 
10301  BaseFunction& at(size_t nRow, size_t nCol) {
10302  return this->mv.at(mM * nCol + nRow);
10303  }
10304 
10336  const BaseFunction& at(size_t nRow, size_t nCol) const {
10337  return this->mv.at(mM * nCol + nRow);
10338  }
10339 
10373  bool operator == (const basic_fmatrix& fm) const {
10374  return this->msize() == fm.msize() && this->nsize() == fm.nsize() && this->_equals(fm);
10375  }
10376 
10410  bool operator != (const basic_fmatrix& fm) const {
10411  return !this->operator == (fm);
10412  }
10413 
10446  this->mv.resize(fm.size());
10447  this->_assign(fm);
10448  this->mM = fm.msize();
10449  this->mN = fm.nsize();
10450  return *this;
10451  }
10452 
10490  basic_fmatrix drv(size_t nVarNum) const
10491  {
10492  basic_fmatrix fmRet(this->mM, this->mN);
10493  fmRet._drv(*this, nVarNum);
10494  return fmRet;
10495  }
10496 
10525  {
10526  this->_simp();
10527  return *this;
10528  }
10529 
10567  basic_fmatrix operator + (const basic_fmatrix& fm) const throw(cvmexception)
10568  {
10569  this->_check_sizes(fm);
10570  basic_fmatrix fmRet(this->mM, this->mN);
10571  fmRet._add(*this, fm);
10572  return fmRet;
10573  }
10574 
10612  basic_fmatrix operator - (const basic_fmatrix& fm) const throw(cvmexception)
10613  {
10614  this->_check_sizes(fm);
10615  basic_fmatrix fmRet(this->mM, this->mN);
10616  fmRet._subtract(*this, fm);
10617  return fmRet;
10618  }
10619 
10661  basic_fmatrix& operator += (const basic_fmatrix& fm) throw(cvmexception)
10662  {
10663  this->_check_sizes(fm);
10664  this->_add(fm);
10665  return *this;
10666  }
10667 
10709  basic_fmatrix& operator -= (const basic_fmatrix& fm) throw(cvmexception)
10710  {
10711  this->_check_sizes(fm);
10712  this->_subtract(fm);
10713  return *this;
10714  }
10715 
10760  {
10761  basic_fmatrix fmRet(this->mM, this->mN);
10762  fmRet.BaseFArray::_mult(*this, f);
10763  return fmRet;
10764  }
10765 
10810  {
10811  basic_fmatrix fmRet(this->mM, this->mN);
10812  fmRet._div(*this, f);
10813  return fmRet;
10814  }
10815 
10856  basic_fmatrix operator *(const T& d) const
10857  {
10858  basic_fmatrix fmRet(this->mM, this->mN);
10859  fmRet.BaseFArray::_mult(*this, d);
10860  return fmRet;
10861  }
10862 
10903  basic_fmatrix operator / (const T& d) const
10904  {
10905  basic_fmatrix fmRet(this->mM, this->mN);
10906  fmRet._div(*this, d);
10907  return fmRet;
10908  }
10909 
10951  this->BaseFArray::_mult(f);
10952  return *this;
10953  }
10954 
10996  {
10997  this->BaseFArray::_div(f);
10998  return *this;
10999  }
11000 
11039  {
11040  this->BaseFArray::_mult(d);
11041  return *this;
11042  }
11043 
11082  {
11083  this->BaseFArray::_div(d);
11084  return *this;
11085  }
11086 
11130  basic_fvector<T> get_row(size_t nRow) const throw(cvmexception)
11131  {
11132  _check_ge(CVM_INDEX_GE, nRow, this->mM);
11133  basic_fvector<T> fvRet(this->mN);
11134  _copy(this->mN, &this->mv.at(nRow), this->mM, &fvRet.mv.at(0), 1);
11135  return fvRet;
11136  }
11137 
11181  basic_fvector<T> get_col(size_t nCol) const throw(cvmexception)
11182  {
11183  _check_ge(CVM_INDEX_GE, nCol, this->mN);
11184  basic_fvector<T> fvRet(this->mM);
11185  _copy(this->mM, &this->mv.at(this->mM * nCol), 1, &fvRet.mv.at(0), 1);
11186  return fvRet;
11187  }
11188 
11236  basic_fmatrix& set_row(size_t nRow, const basic_fvector<T>& fv) throw(cvmexception)
11237  {
11238  _check_ge(CVM_INDEX_GE, nRow, this->mM);
11239  _check_ne(CVM_SIZESMISMATCH, fv.size(), this->nsize());
11240  _copy(this->mN, &fv.mv.at(0), 1, &this->mv.at(nRow), this->mM);
11241  return *this;
11242  }
11243 
11291  basic_fmatrix& set_col(size_t nCol, const basic_fvector<T>& fv) throw(cvmexception)
11292  {
11293  _check_ge(CVM_INDEX_GE, nCol, this->nsize());
11294  _check_ne(CVM_SIZESMISMATCH, fv.size(), this->msize());
11295  _copy(this->mM, &fv.mv.at(0), 1, &this->mv.at(this->mM * nCol), 1);
11296  return *this;
11297  }
11298 
11348  basic_fvector<T> operator *(const basic_fvector<T>& fv) const throw(cvmexception)
11349  {
11350  _check_ne(CVM_SIZESMISMATCH, fv.size(), this->nsize());
11351  basic_fvector<T> vRet(this->msize());
11352  vRet._mult(*this, fv);
11353  return vRet;
11354  }
11355 
11415  basic_fmatrix operator *(const basic_fmatrix& fm) const throw(cvmexception)
11416  {
11417  _check_ne(CVM_SIZESMISMATCH, fm.msize(), this->nsize());
11418  basic_fmatrix mRet(this->msize(), fm.nsize());
11419  mRet._mult(*this, fm);
11420  return mRet;
11421  }
11422 
11485  basic_fmatrix& mult(const basic_fmatrix& fmA, const basic_fmatrix& fmB) throw(cvmexception)
11486  {
11487  _check_ne(CVM_SIZESMISMATCH, fmA.msize(), this->msize());
11488  _check_ne(CVM_SIZESMISMATCH, fmB.nsize(), this->nsize());
11489  _check_ne(CVM_SIZESMISMATCH, fmB.msize(), fmA.nsize());
11490  return this->_mult(fmA, fmB);
11491  }
11492 
11524  friend std::ostream& operator <<(std::ostream& os, const basic_fmatrix<T>& fm)
11525  {
11526  for (size_t i = 0; i < fm.msize(); ++i) {
11527  for (size_t j = 0; j < fm.nsize(); ++j) {
11528  os << fm.mv.at(fm.msize() * j + i) << CFUN_SSPACE;
11529  }
11530  os << std::endl;
11531  }
11532  return os;
11533  }
11534 
11536 protected:
11537  // internal version, it doesn't verify anything
11538  basic_fmatrix& _mult(const basic_fmatrix& fmA, const basic_fmatrix& fmB) throw(cvmexception)
11539  {
11540  for (size_t i = 0; i < this->mM; ++i) {
11541  for (size_t j = 0; j < this->mN; ++j) {
11542  this->mv.at(this->mM * j + i)._scalar_product(fmA.nsize(), &fmA.mv.at(i), this->mM, &fmB.mv.at(fmB.msize() * j), 1);
11543  }
11544  }
11545  return *this;
11546  }
11548 };
11549 
11550 
11558 class rfmatrix : public basic_fmatrix<treal>
11559 {
11560 protected:
11562 
11563 public:
11570  : BaseFMatrix()
11571  {
11572  }
11573 
11596  rfmatrix(size_t m, size_t n)
11597  : BaseFMatrix(m, n)
11598  {
11599  }
11600 
11635  rfmatrix(size_t m, size_t n, const string_array& saInput)
11636  : BaseFMatrix(m, n, saInput)
11637  {
11638  }
11639 
11686  rfmatrix(size_t m, size_t n, const string_array& saVars, const string_array& saBodies,
11687  const string_array& saParameters, const string_array& saMeanings)
11688  : BaseFMatrix(m, n, saVars, saBodies, saParameters, saMeanings)
11689  {
11690  }
11691 
11699  : BaseFMatrix(fm)
11700  {
11701  }
11702 
11707  : BaseFMatrix(std::move(fm))
11708  {
11709  }
11710 
11746  rmatrix ret((tint)this->msize(), (tint)this->nsize());
11747  this->value(ret);
11748  return ret;
11749  }
11750 
11787  rmatrix ret((tint)this->msize(), (tint)this->nsize());
11788  this->value(d, ret);
11789  return ret;
11790  }
11791 
11829  rmatrix ret((tint)this->msize(), (tint)this->nsize());
11830  this->value(d1, d2, ret);
11831  return ret;
11832  }
11833 
11871  rmatrix operator () (treal d1, treal d2, treal d3) const {
11872  rmatrix ret((tint)this->msize(), (tint)this->nsize());
11873  this->value(d1, d2, d3, ret);
11874  return ret;
11875  }
11876 
11917  rmatrix operator () (const treal* pd) const {
11918  rmatrix ret((tint)this->msize(), (tint)this->nsize());
11919  this->value(pd, ret);
11920  return ret;
11921  }
11922 
11923 };
11924 
11925 
11926 
11934 class cfmatrix : public basic_fmatrix<tcomplex>
11935 {
11936 protected:
11938 
11939 public:
11946  : BaseFMatrix()
11947  {
11948  }
11949 
11972  cfmatrix(size_t m, size_t n)
11973  : BaseFMatrix(m, n)
11974  {
11975  }
11976 
12011  cfmatrix(size_t m, size_t n, const string_array& saInput)
12012  : BaseFMatrix(m, n, saInput)
12013  {
12014  }
12015 
12062  cfmatrix(size_t m, size_t n, const string_array& saVars, const string_array& saBodies,
12063  const string_array& saParameters, const string_array& saMeanings)
12064  : BaseFMatrix(m, n, saVars, saBodies, saParameters, saMeanings)
12065  {
12066  }
12067 
12075  : BaseFMatrix(fm)
12076  {
12077  }
12078 
12083  : BaseFMatrix(std::move(fm))
12084  {
12085  }
12086 
12122  cmatrix ret((tint)this->msize(), (tint)this->nsize());
12123  this->value(ret);
12124  return ret;
12125  }
12126 
12163  cmatrix ret((tint)this->msize(), (tint)this->nsize());
12164  this->value(d, ret);
12165  return ret;
12166  }
12167 
12205  cmatrix ret((tint)this->msize(), (tint)this->nsize());
12206  this->value(d1, d2, ret);
12207  return ret;
12208  }
12209 
12248  cmatrix ret((tint)this->msize(), (tint)this->nsize());
12249  this->value(d1, d2, d3, ret);
12250  return ret;
12251  }
12252 
12293  cmatrix operator () (const tcomplex* pd) const {
12294  cmatrix ret((tint)this->msize(), (tint)this->nsize());
12295  this->value(pd, ret);
12296  return ret;
12297  }
12298 
12299 };
12300 
12301 
12302 
12303 
12305 
12306 // specializations:
12307 template<typename T>
12308 class Comparator<T,T>
12309 {
12310 public:
12311  static bool lt(const T& l, const T& r)
12312  {
12313  return l < r;
12314  }
12315  static bool le(const T& l, const T& r)
12316  {
12317  return l <= r;
12318  }
12319  static bool gt(const T& l, const T& r)
12320  {
12321  return l > r;
12322  }
12323  static bool ge(const T& l, const T& r)
12324  {
12325  return l >= r;
12326  }
12327  static bool eq(const T& l, const T& r)
12328  {
12329  return cvm::_abs(l - r) <= cvm::basic_cvmMachMin<T>();
12330  }
12331 };
12332 
12333 template<typename T>
12334 class Comparator<std::complex<T>, std::complex<T> >
12335 {
12336 public:
12337  static bool lt(const std::complex<T>& l, const std::complex<T>& r)
12338  {
12339  return l.real() < r.real();
12340  }
12341  static bool le(const std::complex<T>& l, const std::complex<T>& r)
12342  {
12343  return l.real() <= r.real();
12344  }
12345  static bool gt(const std::complex<T>& l, const std::complex<T>& r)
12346  {
12347  return l.real() > r.real();
12348  }
12349  static bool ge(const std::complex<T>& l, const std::complex<T>& r)
12350  {
12351  return l.real() >= r.real();
12352  }
12353  static bool eq(const std::complex<T>& l, const std::complex<T>& r)
12354  {
12355  return cvm::_abs(l.real() - r.real()) <= cvm::basic_cvmMachMin<T>() &&
12356  cvm::_abs(l.imag() - r.imag()) <= cvm::basic_cvmMachMin<T>();
12357  }
12358 };
12359 
12360 template<typename T>
12361 class Comparator<T,std::complex<T> >
12362 {
12363 public:
12364  static bool lt(const T& l, const std::complex<T>& r)
12365  {
12366  return l < r.real();
12367  }
12368  static bool le(const T& l, const std::complex<T>& r)
12369  {
12370  return l <= r.real();
12371  }
12372  static bool gt(const T& l, const std::complex<T>& r)
12373  {
12374  return l > r.real();
12375  }
12376  static bool ge(const T& l, const std::complex<T>& r)
12377  {
12378  return l >= r.real();
12379  }
12380  static bool eq(const T& l, const std::complex<T>& r)
12381  {
12382  return cvm::_abs(l - r.real()) <= cvm::basic_cvmMachMin<T>() &&
12383  cvm::_abs(r.imag()) <= cvm::basic_cvmMachMin<T>();
12384  }
12385 };
12386 
12387 template<typename T>
12388 class Comparator<std::complex<T>, T>
12389 {
12390 public:
12391  static bool lt(const std::complex<T>& l, const T& r)
12392  {
12393  return l.real() < r;
12394  }
12395  static bool le(const std::complex<T>& l, const T& r)
12396  {
12397  return l.real() <= r;
12398  }
12399  static bool gt(const std::complex<T>& l, const T& r)
12400  {
12401  return l.real() > r;
12402  }
12403  static bool ge(const std::complex<T>& l, const T& r)
12404  {
12405  return l.real() >= r;
12406  }
12407  static bool eq(const std::complex<T>& l, const T& r)
12408  {
12409  return cvm::_abs(l.real() - r) <= cvm::basic_cvmMachMin<T>() &&
12410  cvm::_abs(l.imag()) <= cvm::basic_cvmMachMin<T>();
12411  }
12412 };
12414 
12415 // end-user classes
12418 
12420 
12421 #endif // _CFUN_H
12422