Qucs-core  0.0.18
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
differentiate.cpp
Go to the documentation of this file.
1 /*
2  * differentiate.cpp - the Qucs equation differentiator implementations
3  *
4  * Copyright (C) 2007, 2008 Stefan Jahn <stefan@lkcc.org>
5  *
6  * This is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * This software is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this package; see the file COPYING. If not, write to
18  * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  *
21  * $Id$
22  *
23  */
24 
25 #if HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <ctype.h>
33 #include <cmath>
34 
35 #include "logging.h"
36 #include "complex.h"
37 #include "object.h"
38 #include "consts.h"
39 #include "equation.h"
40 #include "differentiate.h"
41 
42 using namespace qucs;
43 using namespace qucs::eqn;
44 
45 // Short helper macros.
46 #define C(con) ((constant *) (con))
47 #define A(con) ((application *) (con))
48 #define R(con) ((reference *) (con))
49 #define D(con) (C(con)->d)
50 
51 #define isConst(n) ((n)->getTag()==CONSTANT && C(n)->getType()==TAG_DOUBLE)
52 #define isRef(r,v) ((r)->getTag()==REFERENCE && !strcmp(R(r)->n,v))
53 #define isZero(n) (isConst(n) && D(n) == 0.0)
54 #define isOne(n) (isConst(n) && D(n) == 1.0)
55 #define isNeg(n) (isConst(n) && D(n) == -1.0)
56 #define isEuler(n) ((isConst(n) && D(n) == M_E) || isRef(n,"e"))
57 #define isval(n,v) (isConst(n) && D(n) == v)
58 
59 #define isVar(v) ((v)->getTag()==REFERENCE)
60 #define isApp(v) ((v)->getTag()==APPLICATION)
61 #define isMul(v) (isApp(v) && !strcmp(A(v)->n,"*"))
62 #define isSqr(v) (isApp(v) && !strcmp(A(v)->n,"sqr"))
63 
64 #define retCon(val) \
65  constant * res = new constant (TAG_DOUBLE); res->d = val; return res;
66 #define defCon(def,val) \
67  constant * def = new constant (TAG_DOUBLE); def->d = val;
68 #define defRef(def,var) \
69  reference * def = new reference (); def->n = strdup (var);
70 #define retApp1(op,f0) \
71  application * res = new application (); res->n = strdup (op); \
72  res->nargs = 1; res->args = f0; res->args->setNext (NULL); return res;
73 #define defApp1(def,op,f0) \
74  application * def = new application (); def->n = strdup (op); \
75  def->nargs = 1; def->args = f0; def->args->setNext (NULL);
76 #define defApp2(def,op,f0,f1) \
77  application * def = new application (); def->n = strdup (op); \
78  def->nargs = 2; def->args = f0; def->args->append (f1);
79 #define retApp2(op,f0,f1) \
80  application * res = new application (); res->n = strdup (op); \
81  res->nargs = 2; res->args = f0; res->args->append (f1); return res;
82 #define retApp3(op,f0,f1,f2) \
83  application * res = new application (); res->n = strdup (op); \
84  res->nargs = 3; res->args = f0; res->args->append (f1); \
85  res->args->append (f2); return res;
86 #define defApp3(def,op,f0,f1,f2) \
87  application * def = new application (); def->n = strdup (op); \
88  def->nargs = 3; def->args = f0; def->args->append (f1); \
89  def->args->append (f2);
90 
91 #define _A(idx) app->args->get(idx)
92 #define _A0 _A(0)
93 #define _A1 _A(1)
94 #define _A2 _A(2)
95 #define _D0 _A(0)->differentiate (derivative)
96 #define _D1 _A(1)->differentiate (derivative)
97 #define _D2 _A(2)->differentiate (derivative)
98 
99 #define _AF0(var) node * var = _A0;
100 #define _AF1(var) node * var = _A1;
101 #define _AF2(var) node * var = _A2;
102 #define _AD0(var) node * var = _D0;
103 #define _AD1(var) node * var = _D1;
104 #define _AD2(var) node * var = _D2;
105 
106 #define _AA(a,idx) A(a)->args->get(idx)
107 #define _AA0(a) _AA(a,0)
108 #define _AA1(a) _AA(a,1)
109 
110 #define _AAF0(a,var) node * var = _AA0(a);
111 #define _AAF1(a,var) node * var = _AA1(a);
112 
113 node * differentiate::plus_binary (application * app, char * derivative) {
114  _AD0 (d0);
115  _AD1 (d1);
116  if (!isConst (d0) && !isConst (d1)) {
117  retApp2 ("+", d0, d1);
118  }
119  return plus_reduce (d0, d1);
120 }
121 
122 node * differentiate::plus_unary (application * app, char * derivative) {
123  _AD0 (d0);
124  return d0;
125 }
126 
128  if (isZero (f0) && isZero (f1)) {
129  delete f0; delete f1;
130  retCon (0);
131  } else if (isZero (f0)) {
132  delete f0;
133  return f1;
134  } else if (isZero (f1)) {
135  delete f1;
136  return f0;
137  } else if (isConst (f0) && isConst (f1)) {
138  nr_double_t t = D(f0) + D(f1);
139  delete f0; delete f1;
140  retCon (t);
141  } else {
142  retApp2 ("+", f0, f1);
143  }
144 }
145 
146 node * differentiate::minus_binary (application * app, char * derivative) {
147  _AD0 (d0);
148  _AD1 (d1);
149  if (!isConst (d0) && !isConst (d1)) {
150  retApp2 ("-", d0, d1);
151  }
152  return minus_reduce (d0, d1);
153 }
154 
155 node * differentiate::minus_unary (application * app, char * derivative) {
156  _AD0 (d0);
157  return minus_reduce (d0);
158 }
159 
161  if (isZero (f0)) {
162  delete f0;
163  retCon (0);
164  } else if (isConst (f0)) {
165  nr_double_t t = -D(f0);
166  delete f0;
167  retCon (t);
168  }
169  retApp1 ("-", f0);
170 }
171 
173  if (isZero (f0) && isZero (f1)) {
174  delete f0; delete f1;
175  retCon (0);
176  } else if (isZero (f0)) {
177  delete f0;
178  return minus_reduce (f1);
179  } else if (isZero (f1)) {
180  delete f1;
181  return f0;
182  } else if (isConst (f0) && isConst (f1)) {
183  nr_double_t t = D(f0) - D(f1);
184  delete f0; delete f1;
185  retCon (t);
186  } else {
187  retApp2 ("-", f0, f1);
188  }
189 }
190 
191 node * differentiate::times (application * app, char * derivative) {
192  _AF0 (f0);
193  _AF1 (f1);
194  if (isConst (f0) && isConst (f1)) {
195  retCon (0);
196  }
197  _AD0 (d0);
198  _AD1 (d1);
199  node * t1 = times_reduce (f0->recreate(), d1);
200  node * t2 = times_reduce (f1->recreate(), d0);
201  return plus_reduce (t1, t2);
202 }
203 
205  if (isZero (f0) || isZero (f1)) {
206  delete f0; delete f1;
207  retCon (0);
208  } else if (isOne (f0)) {
209  delete f0;
210  return f1;
211  } else if (isNeg (f0)) {
212  delete f0;
213  return minus_reduce (f1);
214  } else if (isOne (f1)) {
215  delete f1;
216  return f0;
217  } else if (isNeg (f1)) {
218  delete f1;
219  return minus_reduce (f0);
220  } else if (isConst (f0) && isConst (f1)) {
221  nr_double_t t = D(f0) * D(f1);
222  delete f0; delete f1;
223  retCon (t);
224  } else {
225  retApp2 ("*", f0, f1);
226  }
227 }
228 
229 node * differentiate::over (application * app, char * derivative) {
230  _AF0 (f0);
231  _AF1 (f1);
232  if (isConst (f0) && isConst (f1)) {
233  retCon (0);
234  }
235  _AD0 (d0);
236  _AD1 (d1);
237  node * t1 = times_reduce (f0->recreate(), d1);
238  node * t2 = times_reduce (f1->recreate(), d0);
239  node * t3 = minus_reduce (t2, t1);
240  node * t4 = sqr_reduce (f1->recreate());
241  return over_reduce (t3, t4);
242 }
243 
245  if (isOne (f0) && isOne (f1)) {
246  delete f0; delete f1;
247  retCon (1);
248  } else if (isZero (f0)) {
249  delete f0; delete f1;
250  retCon (0);
251  } else if (isConst (f0) && isConst (f1)) {
252  if (isZero (f1)) {
253  retApp2 ("/", f0, f1);
254  }
255  nr_double_t t = D(f0) / D(f1);
256  delete f0; delete f1;
257  retCon (t);
258  } else if (isOne (f1)) {
259  delete f1;
260  return f0;
261  } else if (isNeg (f1)) {
262  delete f1;
263  return minus_reduce (f0);
264  } else {
265  over_reduce_adv (f0, f1);
266  retApp2 ("/", f0, f1);
267  }
268 }
269 
271  if (isVar (f0)) {
272  if (isSqr (f1)) {
273  _AAF0 (f1,g1);
274  if (isVar (g1)) {
275  if (!strcmp (R(f0)->n, R(g1)->n)) {
276  defCon (one, 1);
277  reference * var = new reference (*R(g1));
278  delete f0;
279  delete f1;
280  f0 = one;
281  f1 = var;
282  }
283  }
284  }
285  }
286 }
287 
288 node * differentiate::power (application * app, char * derivative) {
289  _AF0 (f0);
290  _AF1 (f1);
291  if (isConst (f0) && isConst (f1)) {
292  retCon (0);
293  }
294  _AD0 (d0);
295  _AD1 (d1);
296  if (isZero (d1)) {
297  defCon (one, 1);
298  node * t1 = minus_reduce (f1->recreate(), one);
299  node * t2 = power_reduce (f0->recreate(), t1);
300  node * t3 = times_reduce (f1->recreate(), t2);
301  return times_reduce (t3, d0);
302  }
303  else {
304  node * t1 = power_reduce (f0->recreate(), f1->recreate());
305  node * ln = ln_reduce (f0->recreate());
306  node * t2 = times_reduce (d1, ln);
307  node * t3 = times_reduce (f1->recreate(), d0);
308  node * t4 = over_reduce (t3, f0->recreate());
309  node * t5 = plus_reduce (t2, t4);
310  return times_reduce (t1, t5);
311  }
312 }
313 
315  if (isOne (f0)) {
316  delete f0; delete f1;
317  retCon (1);
318  } else if (isZero (f0)) {
319  delete f0; delete f1;
320  retCon (0);
321  } else if (isConst (f0) && isConst (f1)) {
322  if (isZero (f1)) {
323  delete f0; delete f1;
324  retCon (1);
325  }
326  nr_double_t t = std::pow (D(f0), D(f1));
327  delete f0; delete f1;
328  retCon (t);
329  } else if (isOne (f1)) {
330  delete f1;
331  return f0;
332  } else {
333  retApp2 ("^", f0, f1);
334  }
335 }
336 
337 node * differentiate::ln (application * app, char * derivative) {
338  _AF0 (f0);
339  _AD0 (d0);
340  return over_reduce (d0, f0->recreate ());
341 }
342 
344  if (isOne (f0)) {
345  delete f0;
346  retCon (0);
347  } else if (isEuler (f0)) {
348  delete f0;
349  retCon (1);
350  }
351  retApp1 ("ln", f0);
352 }
353 
354 node * differentiate::log10 (application * app, char * derivative) {
355  _AF0 (f0);
356  _AD0 (d0);
357  node * t1 = over_reduce (d0, f0->recreate ());
358  defCon (ten, 10);
359  return over_reduce (t1, ln_reduce (ten));
360 }
361 
362 node * differentiate::log2 (application * app, char * derivative) {
363  _AF0 (f0);
364  _AD0 (d0);
365  node * t1 = over_reduce (d0, f0->recreate ());
366  defCon (two, 2);
367  return over_reduce (t1, ln_reduce (two));
368 }
369 
370 node * differentiate::sqrt (application * app, char * derivative) {
371  _AF0 (f0);
372  _AD0 (d0);
373  defCon (half, 0.5);
374  node * t1 = times_reduce (half, d0);
375  node * t2 = sqrt_reduce (f0->recreate());
376  return over_reduce (t1, t2);
377 }
378 
380  if (isOne (f0)) {
381  delete f0;
382  retCon (1);
383  } else if (isZero (f0)) {
384  delete f0;
385  retCon (0);
386  }
387  retApp1 ("sqrt", f0);
388 }
389 
390 node * differentiate::app_reduce (const char * func, node * d0, node * f0) {
391  if (isOne (d0)) {
392  delete d0;
393  retApp1 (func, f0);
394  } else if (isZero (d0)) {
395  delete d0; delete f0;
396  retCon (0);
397  }
398  defApp1 (app, func, f0);
399  return times_reduce (d0, app);
400 }
401 
402 node * differentiate::exp (application * app, char * derivative) {
403  _AF0 (f0);
404  _AD0 (d0);
405  return app_reduce ("exp", d0, f0->recreate());
406 }
407 
408 node * differentiate::limexp (application * app, char * derivative) {
409  _AF0 (f0);
410  _AD0 (d0);
411  defCon (lexp, ::exp (M_LIMEXP));
412  defCon (lcon, M_LIMEXP);
413  defApp2 (ask, "<", f0->recreate(), lcon);
414  defApp1 (exp, "exp", f0->recreate());
415  defApp3 (ite, "?:", ask, exp, lexp);
416  return times_reduce (d0, ite);
417 }
418 
419 node * differentiate::sin (application * app, char * derivative) {
420  _AF0 (f0);
421  _AD0 (d0);
422  return app_reduce ("cos", d0, f0->recreate());
423 }
424 
425 node * differentiate::cos (application * app, char * derivative) {
426  _AF0 (f0);
427  _AD0 (d0);
428  node * t1 = minus_reduce (d0);
429  return app_reduce ("sin", t1, f0->recreate());
430 }
431 
432 node * differentiate::tan (application * app, char * derivative) {
433  _AF0 (f0);
434  _AD0 (d0);
435  defApp1 (sec, "sec", f0->recreate());
436  defCon (two, 2);
437  node * t1 = power_reduce (sec, two);
438  return times_reduce (d0, t1);
439 }
440 
441 node * differentiate::sec (application * app, char * derivative) {
442  _AF0 (f0);
443  _AD0 (d0);
444  defApp1 (sin, "sin", f0->recreate());
445  defApp1 (cos, "cos", f0->recreate());
446  defCon (two, 2);
447  node * t1 = power_reduce (cos, two);
448  node * t2 = over_reduce (sin, t1);
449  return times_reduce (d0, t2);
450 }
451 
452 node * differentiate::cot (application * app, char * derivative) {
453  _AF0 (f0);
454  _AD0 (d0);
455  defApp1 (cosec, "cosec", f0->recreate());
456  defCon (two, 2);
457  node * t1 = minus_reduce (d0);
458  node * t2 = power_reduce (cosec, two);
459  return times_reduce (t1, t2);
460 }
461 
462 node * differentiate::cosec (application * app, char * derivative) {
463  _AF0 (f0);
464  _AD0 (d0);
465  defApp1 (sin, "sin", f0->recreate());
466  defApp1 (cos, "cos", f0->recreate());
467  defCon (two, 2);
468  node * t1 = minus_reduce (d0);
469  node * t2 = power_reduce (sin, two);
470  node * t3 = over_reduce (cos, t2);
471  return times_reduce (t1, t3);
472 }
473 
474 node * differentiate::abs (application * app, char * derivative) {
475  _AF0 (f0);
476  _AD0 (d0);
477  return app_reduce ("sign", d0, f0->recreate());
478 }
479 
481  retCon (0);
482 }
483 
485  retCon (0);
486 }
487 
488 node * differentiate::arcsin (application * app, char * derivative) {
489  _AF0 (f0);
490  _AD0 (d0);
491  node * sqr = sqr_reduce (f0->recreate());
492  defCon (one, 1);
493  node * t1 = minus_reduce (one, sqr);
494  node * t2 = sqrt_reduce (t1);
495  return over_reduce (d0, t2);
496 }
497 
498 node * differentiate::square (application * app, char * derivative) {
499  _AF0 (f0);
500  _AD0 (d0);
501  defCon (two, 2);
502  node * t1 = times_reduce (two, d0);
503  return times_reduce (t1, f0->recreate());
504 }
505 
507  if (isOne (f0)) {
508  delete f0;
509  retCon (1);
510  } else if (isZero (f0)) {
511  delete f0;
512  retCon (0);
513  } else if (isConst (f0)) {
514  nr_double_t t = D(f0) * D(f0);
515  delete f0;
516  retCon (t);
517  } else {
518  retApp1 ("sqr", f0);
519  }
520 }
521 
522 node * differentiate::arccos (application * app, char * derivative) {
523  _AF0 (f0);
524  _AD0 (d0);
525  node * sqr = sqr_reduce (f0->recreate());
526  defCon (one, 1);
527  node * t1 = minus_reduce (one, sqr);
528  node * t2 = sqrt_reduce (t1);
529  node * t3 = minus_reduce (d0);
530  return over_reduce (t3, t2);
531 }
532 
533 node * differentiate::arctan (application * app, char * derivative) {
534  _AF0 (f0);
535  _AD0 (d0);
536  node * sqr = sqr_reduce (f0->recreate());
537  defCon (one, 1);
538  node * t1 = plus_reduce (one, sqr);
539  return over_reduce (d0, t1);
540 }
541 
542 node * differentiate::arccot (application * app, char * derivative) {
543  _AF0 (f0);
544  _AD0 (d0);
545  node * sqr = sqr_reduce (f0->recreate());
546  defCon (one, 1);
547  node * t1 = plus_reduce (one, sqr);
548  node * t2 = minus_reduce (d0);
549  return over_reduce (t2, t1);
550 }
551 
552 node * differentiate::arcsec (application * app, char * derivative) {
553  _AF0 (f0);
554  _AD0 (d0);
555  node * sqr = sqr_reduce (f0->recreate());
556  defCon (one, 1);
557  node * t1 = minus_reduce (sqr, one);
558  node * t2 = sqrt_reduce (t1);
559  node * t3 = times_reduce (f0->recreate(), t2);
560  return over_reduce (d0, t3);
561 }
562 
563 node * differentiate::arccosec (application * app, char * derivative) {
564  _AF0 (f0);
565  _AD0 (d0);
566  node * sqr = sqr_reduce (f0->recreate());
567  defCon (one, 1);
568  node * t1 = minus_reduce (sqr, one);
569  node * t2 = sqrt_reduce (t1);
570  node * t3 = times_reduce (f0->recreate(), t2);
571  node * t4 = minus_reduce (d0);
572  return over_reduce (t4, t3);
573 }
574 
575 node * differentiate::sinh (application * app, char * derivative) {
576  _AF0 (f0);
577  _AD0 (d0);
578  return app_reduce ("cosh", d0, f0->recreate());
579 }
580 
581 node * differentiate::cosh (application * app, char * derivative) {
582  _AF0 (f0);
583  _AD0 (d0);
584  return app_reduce ("sinh", d0, f0->recreate());
585 }
586 
587 node * differentiate::tanh (application * app, char * derivative) {
588  _AF0 (f0);
589  _AD0 (d0);
590  defApp1 (cosh, "cosh", f0->recreate());
591  defCon (two, 2);
592  node * t1 = power_reduce (cosh, two);
593  return over_reduce (d0, t1);
594 }
595 
596 node * differentiate::coth (application * app, char * derivative) {
597  _AF0 (f0);
598  _AD0 (d0);
599  defApp1 (sinh, "sinh", f0->recreate());
600  defCon (two, 2);
601  node * t1 = power_reduce (sinh, two);
602  node * t2 = minus_reduce (d0);
603  return over_reduce (t2, t1);
604 }
605 
606 node * differentiate::artanh (application * app, char * derivative) {
607  _AF0 (f0);
608  _AD0 (d0);
609  node * sqr = sqr_reduce (f0->recreate());
610  defCon (one, 1);
611  node * t1 = minus_reduce (one, sqr);
612  return over_reduce (d0, t1);
613 }
614 
615 node * differentiate::arcoth (application * app, char * derivative) {
616  _AF0 (f0);
617  _AD0 (d0);
618  node * sqr = sqr_reduce (f0->recreate());
619  defCon (one, 1);
620  node * t1 = minus_reduce (sqr, one);
621  node * t2 = minus_reduce (d0);
622  return over_reduce (t2, t1);
623 }
624 
625 node * differentiate::arcosh (application * app, char * derivative) {
626  _AF0 (f0);
627  _AD0 (d0);
628  node * sqr = sqr_reduce (f0->recreate());
629  defCon (one, 1);
630  node * t1 = minus_reduce (sqr, one);
631  node * t2 = sqrt_reduce (t1);
632  return over_reduce (d0, t2);
633 }
634 
635 node * differentiate::arsinh (application * app, char * derivative) {
636  _AF0 (f0);
637  _AD0 (d0);
638  node * sqr = sqr_reduce (f0->recreate());
639  defCon (one, 1);
640  node * t1 = plus_reduce (sqr, one);
641  node * t2 = sqrt_reduce (t1);
642  return over_reduce (d0, t2);
643 }
644 
645 node * differentiate::arsech (application * app, char * derivative) {
646  _AF0 (f0);
647  _AD0 (d0);
648  node * sqr = sqr_reduce (f0->recreate());
649  defCon (one, 1);
650  node * t1 = minus_reduce (one, sqr);
651  node * t2 = sqrt_reduce (t1);
652  node * t3 = times_reduce (f0->recreate(), t2);
653  node * t4 = minus_reduce (d0);
654  return over_reduce (t4, t3);
655 }
656 
657 node * differentiate::arcosech (application * app, char * derivative) {
658  _AF0 (f0);
659  _AD0 (d0);
660  node * sqr = sqr_reduce (f0->recreate());
661  defCon (one, 1);
662  node * t1 = plus_reduce (one, sqr);
663  node * t2 = sqrt_reduce (t1);
664  node * t3 = times_reduce (f0->recreate(), t2);
665  node * t4 = minus_reduce (d0);
666  return over_reduce (t4, t3);
667 }
668 
669 node * differentiate::ifthenelse (application * app, char * derivative) {
670  _AF0 (f0);
671  _AD1 (d1);
672  _AD2 (d2);
673  if (isConst (d1) && isConst (d2)) {
674  if (D(d1) == D(d2)) {
675  nr_double_t t = D(d1);
676  delete d1; delete d2;
677  retCon (t);
678  }
679  }
680  retApp3 ("?:", f0->recreate(), d1, d2);
681 }
682 
683 node * differentiate::sinc (application * app, char * derivative) {
684  _AF0 (f0);
685  _AD0 (d0);
686  defApp1 (sinc, "sinc", f0->recreate());
687  defApp1 (cos, "cos", f0->recreate());
688  node * t1 = minus_reduce (cos, sinc);
689  node * t2 = over_reduce (t1, f0->recreate());
690  return times_reduce (d0, t2);
691 }
692 
693 node * differentiate::norm (application * app, char * derivative) {
694  _AF0 (f0);
695  _AD0 (d0);
696  defCon (two, 2);
697  node * t1 = times_reduce (d0, two);
698  return times_reduce (t1, f0->recreate());
699 }
700 
701 node * differentiate::xhypot (application * app, char * derivative) {
702  _AF0 (f0);
703  _AF1 (f1);
704  _AD0 (d0);
705  _AD1 (d1);
706  node * t1 = hypot_reduce (f0->recreate(), f1->recreate());
707  node * t2 = times_reduce (d0, f0->recreate());
708  node * t3 = times_reduce (d1, f1->recreate());
709  node * t4 = plus_reduce (t2, t3);
710  return over_reduce (t4, t1);
711 }
712 
714  if (isZero (f0) && isZero (f1)) {
715  delete f0; delete f1;
716  retCon (0);
717  } else if (isZero (f0)) {
718  delete f0;
719  return sqrt_reduce (sqr_reduce (f1));
720  } else if (isZero (f1)) {
721  delete f1;
722  return sqrt_reduce (sqr_reduce (f0));
723  } else if (isConst (f0) && isConst (f1)) {
724  nr_double_t t = ::xhypot (D(f0), D(f1));
725  delete f0; delete f1;
726  retCon (t);
727  } else {
728  retApp2 ("hypot", f0, f1);
729  }
730 }
731 
732 #include "constants.h"
733 
734 node * differentiate::vt (application * app, char * derivative) {
735  _AD0 (d0);
736  defCon (con, kBoverQ);
737  return times_reduce (d0, con);
738 }
739 
740 // List of differentiators.
742  { "+", differentiate::plus_binary, 2 },
743  { "+", differentiate::plus_unary, 1 },
744  { "-", differentiate::minus_binary, 2 },
745  { "-", differentiate::minus_unary, 1 },
746  { "*", differentiate::times, 2 },
747  { "/", differentiate::over, 2 },
748  { "^", differentiate::power, 2 },
749 
750  { "?:", differentiate::ifthenelse, 3 },
751 
752  { "ln", differentiate::ln, 1 },
753  { "log10", differentiate::log10, 1 },
754  { "log2", differentiate::log2, 1 },
755  { "sqrt", differentiate::sqrt, 1 },
756  { "exp", differentiate::exp, 1 },
757  { "sinc", differentiate::sinc, 1 },
758  { "norm", differentiate::norm, 1 },
759  { "sin", differentiate::sin, 1 },
760  { "cos", differentiate::cos, 1 },
761  { "tan", differentiate::tan, 1 },
762  { "sec", differentiate::sec, 1 },
763  { "cot", differentiate::cot, 1 },
764  { "cosec", differentiate::cosec, 1 },
765  { "abs", differentiate::abs, 1 },
766  { "step", differentiate::step, 1 },
767  { "sign", differentiate::sign, 1 },
768  { "arcsin", differentiate::arcsin, 1 },
769  { "arccos", differentiate::arccos, 1 },
770  { "arctan", differentiate::arctan, 1 },
771  { "arccot", differentiate::arccot, 1 },
772  { "arcsec", differentiate::arcsec, 1 },
773  { "arccosec", differentiate::arccosec, 1 },
774  { "sqr", differentiate::square, 1 },
775  { "sinh", differentiate::sinh, 1 },
776  { "cosh", differentiate::cosh, 1 },
777  { "tanh", differentiate::tanh, 1 },
778  { "coth", differentiate::coth, 1 },
779  { "arsinh", differentiate::arsinh, 1 },
780  { "arcosh", differentiate::arcosh, 1 },
781  { "artanh", differentiate::artanh, 1 },
782  { "arcoth", differentiate::arcoth, 1 },
783  { "arsech", differentiate::arsech, 1 },
784  { "arcosech", differentiate::arcosech, 1 },
785  { "hypot", differentiate::xhypot, 2 },
786  { "limexp", differentiate::limexp, 1 },
787  { "vt", differentiate::vt, 1 },
788 
789  { NULL, NULL, 0 /* end of list */ }
790 };
static node * sec(application *, char *)
#define isEuler(n)
#define defApp2(def, op, f0, f1)
static node * sqrt_reduce(node *)
static node * times(application *, char *)
static node * limexp(application *, char *)
static node * power_reduce(node *, node *)
#define retCon(val)
#define isConst(n)
static node * plus_reduce(node *, node *)
nr_complex_t pow(const nr_complex_t z, const nr_double_t d)
Compute power function with real exponent.
Definition: complex.cpp:238
static node * over(application *, char *)
#define retApp3(op, f0, f1, f2)
static node * app_reduce(const char *, node *, node *)
t
Definition: parse_vcd.y:290
static node * arcoth(application *, char *)
static node * times_reduce(node *, node *)
static node * sqr_reduce(node *)
Global physical constants header file.
#define _AD0(var)
#define _AAF0(a, var)
static node * log2(application *, char *)
n
Definition: parse_citi.y:147
#define defApp1(def, op, f0)
static void over_reduce_adv(node *&, node *&)
static node * sqrt(application *, char *)
static node * square(application *, char *)
#define isNeg(n)
#define _AD2(var)
static node * sinc(application *, char *)
static node * abs(application *, char *)
#define R(con)
static node * ln(application *, char *)
nr_complex_t sqr(const nr_complex_t z)
Square of complex number.
Definition: complex.cpp:673
#define M_LIMEXP
LIMEXP.
Definition: consts.h:101
static node * cot(application *, char *)
static node * vt(application *, char *)
static node * sinh(application *, char *)
static node * plus_binary(application *, char *)
#define defApp3(def, op, f0, f1, f2)
static node * arcosech(application *, char *)
#define kBoverQ
Boltzmann constant over Elementary charge ( )
Definition: constants.h:68
static node * tanh(application *, char *)
static node * sign(application *, char *)
#define isSqr(v)
static node * step(application *, char *)
static node * plus_unary(application *, char *)
static node * sin(application *, char *)
static node * xhypot(application *, char *)
static node * ln_reduce(node *)
#define _AF1(var)
static node * arcsin(application *, char *)
static node * norm(application *, char *)
#define retApp2(op, f0, f1)
Global math constants header file.
struct differentiation_t differentiations[]
static node * hypot_reduce(node *, node *)
static node * tan(application *, char *)
static node * arcosh(application *, char *)
#define isVar(v)
static node * power(application *, char *)
static node * exp(application *, char *)
static node * minus_unary(application *, char *)
static node * arccos(application *, char *)
static node * minus_binary(application *, char *)
#define _AD1(var)
static node * over_reduce(node *, node *)
static node * arccosec(application *, char *)
static node * cosh(application *, char *)
virtual node * recreate(void)
Definition: equation.h:110
static node * ifthenelse(application *, char *)
static node * arcsec(application *, char *)
static node * arccot(application *, char *)
#define retApp1(op, f0)
static node * minus_reduce(node *, node *)
var
Definition: parse_citi.y:145
#define defCon(def, val)
static node * log10(application *, char *)
static node * arctan(application *, char *)
static node * cosec(application *, char *)
#define isOne(n)
#define D(con)
static node * arsech(application *, char *)
#define isZero(n)
#define _AF0(var)
static node * coth(application *, char *)
static node * arsinh(application *, char *)
static node * artanh(application *, char *)
static node * cos(application *, char *)