1 //                                               -*- C++ -*-
2 /**
3  *  @brief symbolic expression (base classes and functionality)
4  *
5  *  Copyright (C) 2008-2010 Leo Liberti
6  *
7  *  This library is free software: you can redistribute it and/or modify
8  *  it under the terms of the GNU Lesser General Public License as published by
9  *  the Free Software Foundation, either version 3 of the License, or
10  *  (at your option) any later version.
11  *
12  *  This library is distributed in the hope that it will be useful,
13  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  *  GNU Lesser General Public License for more details.
16  *
17  *  You should have received a copy of the GNU Lesser General Public License
18  *  along with this library.  If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include <string>
23 #include <sstream>
24 #include <cmath>
25 #include <algorithm>
26 #include <cassert>
27 #include <iomanip>
28 
29 #include "expression.h"
30 
31 namespace Ev3
32 {
33 
34 ////////////// auxiliary functions ///////////////
35 
36 //#define VNAMEIDXCHAR "_"
37 #define VNAMEIDXCHAR ""
38 
39 #define ISINTTOLERANCE 1e-8
40 
is_integer(double a)41 static bool is_integer(double a)
42 {
43   double b = std::abs(a);
44   int bi = (int) round(b);
45   return (std::abs(b - bi) < ISINTTOLERANCE);
46 }
47 
is_even(double a)48 static bool is_even(double a)
49 {
50   if (is_integer(a))
51   {
52     int ai = (int) round(a);
53     return (ai % 2 == 0);
54   }
55   return false;
56 }
57 
is_odd(double a)58 static bool is_odd(double a)
59 {
60   if (is_integer(a))
61   {
62     int ai = (int) round(a);
63     return (ai % 2 == 1);
64   }
65   return false;
66 }
67 
Ev3NearZero()68 double Ev3NearZero()
69 {
70   // returns a very small positive value
71   return 1 / LARGE;
72 }
73 
Ev3Infinity()74 double Ev3Infinity()
75 {
76   // returns a very large positive value
77   return LARGE;
78 }
79 
80 // create empty
BasicExpression()81 BasicExpression::BasicExpression() { }
82 
83 // create a constant leaf
BasicExpression(const double t)84 BasicExpression::BasicExpression(const double t) : Operand(t) { }
85 
86 // create a constant (integer-valued) leaf
BasicExpression(const Int t)87 BasicExpression::BasicExpression(const Int t) : Operand(t) { }
88 
89 // create an (empty) operator or a variable leaf
BasicExpression(const Int t,const bool isvar)90 BasicExpression::BasicExpression(const Int t,
91                                  const bool isvar) :
92   Operand(t, isvar) { }
93 
94 // create a variable leaf and set coefficient
BasicExpression(const double c,const Int t,const std::string & vn)95 BasicExpression::BasicExpression(const double c,
96                                  const Int t,
97                                  const std::string & vn) :
98   Operand(c, t, vn) { }
99 
100 // user-defined copy constructor with two options
BasicExpression(const Expression & t,const bool iscopy)101 BasicExpression::BasicExpression(const Expression & t,
102                                  const bool iscopy) :
103   Operand(t.GetPointee())
104 {
105   const Int s = t->GetSize();
106   // create a _copy_ of t, subnode by subnode
107   if (iscopy) for (int i = 0; i < s; i++) nodes.push_back(t->GetCopyOfNode(i));
108   // create a copy of the pointers in t
109   else for (int i = 0; i < s; i++) nodes.push_back(t->GetNode(i));
110 }
111 
112 // copy constructor
BasicExpression(const BasicExpression & t)113 BasicExpression::BasicExpression(const BasicExpression & t) : Operand(t)
114 {
115   const Int s = t.GetSize();
116   // necessary for constructs "(BasicExpression) e =" where e already
117   // existed prior to assignment
118   // -- segvs (?)
119   for(int i = 0; i < GetSize(); i++) RecursiveDestroy(GetNodePtr(i));
120   DeleteAllNodes();
121   // create a copy of the subnode pointers in t
122   for (int i = 0; i < s; i++) nodes.push_back(t.GetNode(i));
123 }
124 
125 // destructor
~BasicExpression()126 BasicExpression::~BasicExpression() { }
127 
128 // BasicExpression class methods:
129 
130 
Debug() const131 void BasicExpression::Debug () const
132 {
133   Int s = GetSize();
134   std::cerr << "BasicExpression: Debug:\n";
135   std::cerr << "\tthis   = " << this << std::endl;
136   std::cerr << "\toptype = " << GetOpType() << std::endl;
137   std::cerr << "\tnodes  = " << s << std::endl;
138   for (Int i = 0; i < s; i++) std::cerr << "\tnode " << i << ": " << GetNode(i)->GetOpType() << std::endl;
139 }
140 
Zero()141 void BasicExpression::Zero()
142 {
143   // -- segvs (?)
144   for(int i = 0; i < GetSize(); i++) RecursiveDestroy(GetNodePtr(i));
145   DeleteAllNodes();
146   SetCoeff(1.0);
147   SetExponent(1.0);
148   SetValue(0.0);
149   SetOpType(CONST);
150 }
151 
One()152 void BasicExpression::One()
153 {
154   // -- segvs (?)
155   for(int i = 0; i < GetSize(); i++) RecursiveDestroy(GetNodePtr(i));
156   DeleteAllNodes();
157   SetCoeff(1.0);
158   SetExponent(1.0);
159   SetValue(1.0);
160   SetOpType(CONST);
161 }
162 
PrintTree(const int blanks,const int tabs) const163 std::string BasicExpression::PrintTree(const int blanks,
164                                        const int tabs) const
165 {
166   std::stringstream outbuf;
167   std::string b(blanks, ' ');
168   if (IsLeaf()) outbuf << b << Operand::ToString();
169   else
170   {
171     outbuf << b << "OP[" << GetOpType() << "](" << std::endl;
172     for(int i = 0; i < GetSize(); i++)
173     {
174       outbuf << GetNode(i)->PrintTree(blanks + tabs, tabs);
175       if (i < GetSize() - 1)
176       {
177         outbuf << ",";
178       }
179       outbuf << std::endl;
180     }
181     outbuf << b << ")";
182   }
183   return outbuf.str();
184 }
185 
186 
operator <<(std::ostream & outbuf,const BasicExpression & expr)187 std::ostream & operator<< (std::ostream & outbuf, const BasicExpression & expr)
188 {
189   Int i, s;
190   if (expr.IsLeaf())
191   {
192     // leaf node, use Operand::ToString()
193     outbuf << Operand(expr);
194 
195   }
196   else
197   {
198     double tc( expr.GetCoeff());
199     // operator node
200     if (tc != 1)
201     {
202       if (tc != -1) outbuf << "(" << tc << "*(";
203       else outbuf << "(-(";
204     }
205     s =  expr.GetSize();
206     if (s > 1)
207     {
208       for (i = 0; i < s; i++)
209       {
210         outbuf << "(" << expr.GetNode(i) << ")";
211         if (i < s - 1)
212         {
213           switch( expr.GetOpType())
214           {
215             case SUM:
216               outbuf << "+";
217               break;
218             case DIFFERENCE:
219               outbuf << "-";
220               break;
221             case PRODUCT:
222               outbuf << "*";
223               break;
224             case FRACTION:
225               outbuf << "/";
226               break;
227             case POWER:
228               outbuf << "^";
229               break;
230             default:
231               outbuf << "UNKNOWNOP";
232               break;
233           }
234         }
235       }
236     }
237     else
238     {
239       switch( expr.GetOpType())
240       {
241         case PLUS:
242           break;
243         case MINUS:
244           outbuf << "-";
245           break;
246         case SIN:
247           outbuf << "sin";
248           break;
249         case COS:
250           outbuf << "cos";
251           break;
252         case TAN:
253           outbuf << "tan";
254           break;
255         case ASIN:
256           outbuf << "asin";
257           break;
258         case ACOS:
259           outbuf << "acos";
260           break;
261         case ATAN:
262           outbuf << "atan";
263           break;
264         case SINH:
265           outbuf << "sinh";
266           break;
267         case COSH:
268           outbuf << "cosh";
269           break;
270         case TANH:
271           outbuf << "tanh";
272           break;
273         case ASINH:
274           outbuf << "asinh";
275           break;
276         case ACOSH:
277           outbuf << "acosh";
278           break;
279         case ATANH:
280           outbuf << "atanh";
281           break;
282         case LOG2:
283           outbuf << "log2";
284           break;
285         case LOG10:
286           outbuf << "log10";
287           break;
288         case LOG:
289           outbuf << "log";
290           break;
291         case LN:
292           outbuf << "ln";
293           break;
294         case LNGAMMA:
295           outbuf << "lngamma";
296           break;
297         case GAMMA:
298           outbuf << "gamma";
299           break;
300         case EXP:
301           outbuf << "exp";
302           break;
303         case ERF:
304           outbuf << "erf";
305           break;
306         case ERFC:
307           outbuf << "erfc";
308           break;
309         case SQRT:
310           outbuf << "sqrt";
311           break;
312         case CBRT:
313           outbuf << "cbrt";
314           break;
315         case BESSELJ0:
316           outbuf << "besselJ0";
317           break;
318         case BESSELJ1:
319           outbuf << "besselJ1";
320           break;
321         case BESSELY0:
322           outbuf << "besselY0";
323           break;
324         case BESSELY1:
325           outbuf << "besselY1";
326           break;
327         case SIGN:
328           outbuf << "sign";
329           break;
330         case RINT:
331           outbuf << "rint";
332           break;
333         case ABS:
334           outbuf << "abs";
335           break;
336         case COT:
337           outbuf << "cot";
338           break;
339         case COTH:
340           outbuf << "coth";
341           break;
342         default:
343           outbuf << "UNKNOWNOP";
344       }
345       if (s == 1)
346       {
347         outbuf << "(" << expr.GetNode(0) << ")";
348       }
349       else
350       {
351         // no arguments - error
352         outbuf << "(NOARG)";
353       }
354     }
355     if ( expr.GetCoeff() != 1)
356     {
357       outbuf << "))";
358     }
359   }
360   return outbuf;
361 }
362 
363 
ToString() const364 std::string BasicExpression::ToString() const
365 {
366   std::stringstream outbuf;
367   outbuf << *this;
368   return outbuf.str();
369 }
370 
operator <<(std::ostream & outbuf,const Expression & expr)371 std::ostream & operator<< (std::ostream & outbuf, const Expression & expr)
372 {
373   outbuf << expr.GetPointee();
374   return outbuf;
375 }
376 
377 // is expression this == expression t?
IsEqualTo(const Expression & t) const378 bool BasicExpression::IsEqualTo(const Expression& t) const
379 {
380   //Just in case constant value not consolidated in coeff
381   if (GetOpType() == CONST && t->GetOpType() == CONST)
382   {
383     if (GetValue() == t->GetValue())
384     {
385       return true;
386     }
387     else
388     {
389       return false;
390     }
391   }
392 
393   if (IsEqualToNoCoeff(t))
394   {
395     if (GetCoeff() == t->GetCoeff())
396       return true;
397     else
398       return false;
399   }
400   else
401     return false;
402 }
403 
operator ==(const BasicExpression & t) const404 bool BasicExpression::operator == (const BasicExpression& t) const
405 {
406   // fast checks
407   if (IsLeaf() && t.IsLeaf())
408   {
409     if (GetOpType() == t.GetOpType())
410     {
411       if (GetOpType() == CONST)
412       {
413         // if both are constants, they're always equal up to coefficient
414         return true;
415       }
416       else if (GetOpType() == VAR && GetVarIndex() == t.GetVarIndex() &&
417                GetExponent() == t.GetExponent())
418         return true;
419       else
420         return false;
421     }
422     else
423       return false;
424   }
425   else if ((!IsLeaf()) && (!t.IsLeaf()))
426   {
427     // both BasicExpressions are not leaves, recurse using PRECISE
428     // (i.e. not up to coefficient) form
429     if (GetSize() != t.GetSize())
430       return false;
431     if (GetOpType() != t.GetOpType())
432       return false;
433     Int i;
434     bool ret = true;
435     for (i = 0; i < GetSize(); i++)
436     {
437       if (!(GetNode(i)->IsEqualTo(t.GetNode(i))))
438       {
439         ret = false;
440         break;
441       }
442     }
443     if (ret)
444     {
445       return true;
446     }
447     return false;
448   }
449   else
450     return false;
451 }
452 
IsEqualTo(const double t) const453 bool BasicExpression::IsEqualTo(const double t) const
454 {
455   return (IsLeaf() && GetOpType() == CONST && GetValue() == t);
456 }
457 
NumberOfVariables() const458 int BasicExpression::NumberOfVariables() const
459 {
460   int maxvi = 0;
461   return NumberOfVariables(maxvi);
462 }
463 
NumberOfVariables(int & maxvi) const464 int BasicExpression::NumberOfVariables(int& maxvi) const
465 {
466   int newvi = 0;
467   if (IsVariable())
468   {
469     newvi = GetVarIndex();
470     if (newvi > maxvi)
471     {
472       maxvi = newvi;
473     }
474     return maxvi;
475   }
476   else if (!IsLeaf())
477   {
478     for(int i = 0; i < GetSize(); i++)
479     {
480       newvi = GetNode(i)->NumberOfVariables(maxvi);
481       if (newvi > maxvi)
482       {
483         maxvi = newvi;
484       }
485     }
486     return maxvi;
487   }
488   else
489   {
490     return 0;
491   }
492 }
493 
494 
495 // taken and adapted from operator ==
IsEqualToNoCoeff(const Expression & t) const496 bool BasicExpression::IsEqualToNoCoeff(const Expression & t) const
497 {
498   // fast checks
499   if (IsLeaf() && t->IsLeaf())
500   {
501     if (GetOpType() == t->GetOpType())
502     {
503       if (GetOpType() == CONST)
504       {
505         // if both are constants, they're always equal up to coefficient
506         return true;
507       }
508       else
509       {
510         if (GetOpType() == VAR && GetVarIndex() == t->GetVarIndex() &&
511             GetExponent() == t->GetExponent())
512           return true;
513         else
514           return false;
515       }
516     }
517     else return false;
518   }
519   else if ((!IsLeaf()) && (!t->IsLeaf()))
520   {
521     // both BasicExpressions are not leaves, recurse using PRECISE
522     // (i.e. not up to coefficient) form
523     if (GetSize() != t->GetSize() || GetOpType() != t->GetOpType() ||
524         GetExponent() != t->GetExponent())
525     {
526       return false;
527     }
528     Int i;
529     bool ret = true;
530     for (i = 0; i < GetSize(); i++)
531     {
532       if (!(GetNode(i)->IsEqualTo(t->GetNode(i))))
533       {
534         ret = false;
535         break;
536       }
537     }
538     if (ret)
539     {
540       return true;
541     }
542     return false;
543   }
544   else
545     return false;
546 }
547 
IsEqualBySchema(const Expression & t) const548 bool BasicExpression::IsEqualBySchema(const Expression& t) const
549 {
550   if (IsLeaf() && t->IsLeaf())
551   {
552     if (GetOpType() == t->GetOpType() &&
553         IsLinear() == t->IsLinear())
554     {
555       return true;
556     }
557     else
558     {
559       return false;
560     }
561   }
562   else if ((!IsLeaf()) && (!t->IsLeaf()))
563   {
564     // both BasicExpressions are not leaves, recurse
565     if (GetSize() != t->GetSize())
566     {
567       return false;
568     }
569     if (GetOpType() != t->GetOpType())
570     {
571       return false;
572     }
573     Int i;
574     bool ret = true;
575     for (i = 0; i < GetSize(); i++)
576     {
577       if (!(GetNode(i)->IsEqualBySchema(t->GetNode(i))))
578       {
579         ret = false;
580         break;
581       }
582     }
583     if (ret)
584     {
585       return true;
586     }
587     return false;
588   }
589   else
590   {
591     return false;
592   }
593 }
594 
IsEqualByOperator(const int theoplabel) const595 bool BasicExpression::IsEqualByOperator(const int theoplabel) const
596 {
597   if (GetOpType() == theoplabel)
598   {
599     return true;
600   }
601   else
602   {
603     return false;
604   }
605 }
606 
DependsOnVariable(Int vi) const607 bool BasicExpression::DependsOnVariable(Int vi) const
608 {
609   if (IsLeaf())
610   {
611     if (GetOpType() == VAR)
612     {
613       if (GetVarIndex() == vi)
614         return true;
615       else
616         return false;
617     }
618     else
619       return false;
620   }
621   else
622   {
623     Int i;
624     bool ret = false;
625     for (i = 0; i < GetSize(); i++)
626     {
627       ret = GetNode(i)->DependsOnVariable(vi);
628       if (ret)
629         return true;
630     }
631     return false;
632   }
633 }
634 
DependsLinearlyOnVariable(Int vi) const635 int BasicExpression::DependsLinearlyOnVariable(Int vi) const
636 {
637   if (IsVariable())
638   {
639     if (GetVarIndex() == vi)
640     {
641       if (GetExponent() == 1)
642       {
643         return 1; // depends linearly
644       }
645       else
646       {
647         return 0; // depends nonlinearly
648       }
649     }
650     else
651     {
652       return 2; // doesn't depend on vi at all
653     }
654   }
655   else
656   {
657     int i;
658     int d;
659     bool dependsatall = false;
660     // if node is linear:
661     if (GetOpType() == SUM || GetOpType() == DIFFERENCE ||
662         GetOpType() == PLUS || GetOpType() == MINUS)
663     {
664       for(i = 0; i < GetSize(); i++)
665       {
666         d = GetNode(i)->DependsLinearlyOnVariable(vi);
667         if (d == 0)
668         {
669           // depends nonlinearly, return 0
670           return 0;
671         }
672         if (d == 1)
673         {
674           // depends linearly, record
675           dependsatall = true;
676         }
677       }
678       if (dependsatall)
679       {
680         return 1;
681       }
682       else
683       {
684         return 2;
685       }
686     }
687     else if (GetOpType() == PRODUCT)
688     {
689       int nbBranchesDependingOnVariable = 0;
690       for(i = 0; i < GetSize(); i++)
691       {
692         d = GetNode(i)->DependsLinearlyOnVariable(vi);
693         if (d == 0)
694           return 0;
695 
696         if (d == 1)
697           ++nbBranchesDependingOnVariable;
698       }
699 
700       if (nbBranchesDependingOnVariable == 0)
701         return 2;
702       else if (nbBranchesDependingOnVariable == 1)
703         return 1;
704       else
705         return 0;
706     }
707     else
708     {
709       if (DependsOnVariable(vi))
710       {
711         return 0;  // depends nonlinearly
712       }
713       else
714       {
715         return 2;  // doesn't depend on vi at all
716       }
717     }
718   }
719 }
720 
ConsolidateProductCoeffs()721 void BasicExpression::ConsolidateProductCoeffs()
722 {
723   if (GetOpType() == PRODUCT)
724   {
725     Int i;
726     double tc = GetCoeff();
727     for (i = 0; i < GetSize(); i++)
728     {
729       tc *= GetNode(i)->GetCoeff();
730       GetNode(i)->SetCoeff(1.0);
731     }
732     if (std::abs(tc) < Ev3NearZero())
733     {
734       Zero();
735     }
736     else
737     {
738       SetCoeff(tc);
739     }
740   }
741 }
742 
DistributeCoeffOverSum()743 void BasicExpression::DistributeCoeffOverSum()
744 {
745   if (GetOpType() == SUM)
746   {
747     double tc = GetCoeff();
748     if (tc != 1)
749     {
750       SetCoeff(1.0);
751       Int i;
752       for(i = 0; i < GetSize(); i++)
753       {
754         GetNode(i)->SetCoeff(tc * GetNode(i)->GetCoeff());
755         GetNode(i)->DistributeCoeffOverSum();
756       }
757     }
758   }
759 }
760 
DistributeCoeffOverProduct()761 void BasicExpression::DistributeCoeffOverProduct()
762 {
763   if (GetOpType() == PRODUCT)
764   {
765     double tc = GetCoeff();
766     if (tc != 1 && GetSize() > 0)
767     {
768       SetCoeff(1.0);
769       GetNode(0)->SetCoeff(tc * GetNode(0)->GetCoeff());
770     }
771   }
772 }
773 
774 // enforce constant dependencies (added for MORON - see ../PROGNOTES)
775 // this only acts on the proper leaf nodes
EnforceDependency()776 void BasicExpression::EnforceDependency()
777 {
778   if (IsLeaf())
779   {
780     // nonrecursive
781     EnforceDependencyOnOperand();
782   }
783   else
784   {
785     // recursive
786     int i;
787     for (i = 0; i < GetSize(); i++)
788     {
789       GetNode(i)->EnforceDependency();
790     }
791   }
792 }
793 
794 // substitute a variable with a constant
VariableToConstant(int varindex,double c)795 void BasicExpression::VariableToConstant(int varindex,
796     double c)
797 {
798   if (IsLeaf())
799   {
800     // nonrecursive
801     SubstituteVariableWithConstant(varindex, c);
802   }
803   else
804   {
805     // recursive
806     int i;
807     for (i = 0; i < GetSize(); i++)
808     {
809       GetNode(i)->VariableToConstant(varindex, c);
810     }
811   }
812 }
813 
814 // replace variable indexed v1 with variable indexed v2
ReplaceVariable(int v1,int v2,const std::string & vn)815 void BasicExpression::ReplaceVariable(int v1,
816                                       int v2,
817                                       const std::string & vn)
818 {
819   if (DependsOnVariable(v1))
820   {
821     if (IsVariable() && GetVarIndex() == v1)
822     {
823       SetVarIndex(v2);
824       SetVarName(vn);
825     }
826     else
827     {
828       int i;
829       for(i = 0; i < GetSize(); i++)
830       {
831         GetNode(i)->ReplaceVariable(v1, v2, vn);
832       }
833     }
834   }
835 }
ReplaceVariable(int v1,int v2,const std::string & vn,double c2)836 void BasicExpression::ReplaceVariable(int v1,
837                                       int v2,
838                                       const std::string & vn,
839                                       double c2)
840 {
841   if (DependsOnVariable(v1))
842   {
843     if (IsVariable() && GetVarIndex() == v1)
844     {
845       SetVarIndex(v2);
846       SetVarName(vn);
847       SetCoeff(GetCoeff() * c2);
848     }
849     else
850     {
851       int i;
852       for(i = 0; i < GetSize(); i++)
853       {
854         GetNode(i)->ReplaceVariable(v1, v2, vn, c2);
855       }
856     }
857   }
858 }
859 
860 // replace with a variable the deepest node conforming to schema and
861 // return replaced term or zero expression if no replacement occurs
ReplaceBySchema(int vi,const std::string & vn,const Expression & schema)862 Expression BasicExpression::ReplaceBySchema(int vi,
863     const std::string & vn,
864     const Expression & schema)
865 {
866   Expression ret(0.0);
867   ret = ReplaceBySchemaRecursive(vi, vn, schema);
868   if (ret->IsZero())
869   {
870     // no subnodes with schema found, wor on this one
871     if (IsEqualBySchema(schema))
872     {
873       // this node is according to schema
874       // save (recursively) this into ret
875       ret.SetToCopyOf(*this);
876       // replace with w_vi
877       // -- segvs (?)
878       for(int i = 0; i < GetSize(); i++)
879       {
880         RecursiveDestroy(GetNodePtr(i));
881       }
882       DeleteAllNodes();
883       SetOpType(VAR);
884       SetVarIndex(vi);
885       SetVarName(vn);
886       SetCoeff(1.0);
887       SetExponent(1.0);
888     }
889   }
890   return ret;
891 }
892 
893 // recursive version - works on subnodes, not on current node
ReplaceBySchemaRecursive(int vi,const std::string & vn,const Expression & schema)894 Expression BasicExpression::ReplaceBySchemaRecursive(int vi,
895     const std::string & vn,
896     const Expression & schema)
897 {
898   bool done = false;
899   Expression ret(0.0);
900   for(int i = 0; i < GetSize(); i++)
901   {
902     if (!GetNode(i)->IsLeaf())
903     {
904       ret = GetNode(i)->ReplaceBySchemaRecursive(vi, vn, schema);
905       if (!ret->IsZero())
906       {
907         done = true;
908         break;
909       }
910     }
911     if (!done)
912     {
913       if (GetNode(i)->IsEqualBySchema(schema))
914       {
915         ret = GetNode(i);
916         Expression w(1, vi, vn);
917         GetNodePtr(i)->SetTo(w);
918         done = true;
919         break;
920       }
921     }
922   }
923   return ret;
924 }
925 
926 // replace with a variable the deepest node with given operator label
927 // return replaced term or zero expression if no replacement occurs
ReplaceByOperator(int vi,const std::string & vn,int theoplabel)928 Expression BasicExpression::ReplaceByOperator(int vi,
929     const std::string & vn,
930     int theoplabel)
931 {
932   Expression ret(0.0);
933   ret = ReplaceByOperatorRecursive(vi, vn, theoplabel);
934   if (ret->IsZero())
935   {
936     // no subnodes with schema found, wor on this one
937     if (IsEqualByOperator(theoplabel))
938     {
939       // this node is according to schema
940       // save (recursively) this into ret
941       ret.SetToCopyOf(*this);
942       // replace with w_vi
943       // -- segvs
944       for(int i = 0; i < GetSize(); i++)
945       {
946         RecursiveDestroy(GetNodePtr(i));
947       }
948       DeleteAllNodes();
949       SetOpType(VAR);
950       SetVarIndex(vi);
951       SetVarName(vn);
952       SetCoeff(1.0);
953       SetExponent(1.0);
954     }
955   }
956   return ret;
957 }
958 
959 // recursive version - works on subnodes, not on current node
ReplaceByOperatorRecursive(int vi,const std::string & vn,int theoplabel)960 Expression BasicExpression::ReplaceByOperatorRecursive(int vi,
961     const std::string & vn,
962     int theoplabel)
963 {
964   bool done = false;
965   Expression ret(0.0);
966   for(int i = 0; i < GetSize(); i++)
967   {
968     if (!GetNode(i)->IsLeaf())
969     {
970       ret = GetNode(i)->ReplaceByOperatorRecursive(vi, vn, theoplabel);
971       if (!ret->IsZero())
972       {
973         done = true;
974         break;
975       }
976     }
977     if (!done)
978     {
979       if (GetNode(i)->IsEqualByOperator(theoplabel))
980       {
981         ret = GetNode(i);
982         Expression w(1, vi, vn);
983         GetNodePtr(i)->SetTo(w);
984         done = true;
985         break;
986       }
987     }
988   }
989 
990   return ret;
991 }
992 
ReplaceWithExpression(const Expression & replace)993 void BasicExpression::ReplaceWithExpression(const Expression & replace)
994 {
995   /* // -- segvs (?)
996      for(int i = 0; i < GetSize(); i++) {
997      RecursiveDestroy(GetNodePtr(i));
998      }
999   */
1000   DeleteAllNodes();
1001   if (replace->GetOpType() == VAR)
1002   {
1003     SetVarIndex(replace->GetVarIndex());
1004     SetVarName(replace->GetVarName());
1005     SetCoeff(replace->GetCoeff());
1006     SetExponent(replace->GetExponent());
1007   }
1008   else if (replace->GetOpType() == CONST)
1009   {
1010     SetValue(replace->GetValue());
1011   }
1012   else
1013   {
1014     SetCoeff(replace->GetCoeff());
1015     SetExponent(replace->GetExponent());
1016     SetOpType(replace->GetOpType());
1017   }
1018   for (int i = 0; i < replace->GetSize(); i++)
1019   {
1020     nodes.push_back(replace->GetNode(i));
1021   }
1022 }
1023 
1024 
ReplaceSubexpression(const Expression & needle,const Expression & replace)1025 int BasicExpression::ReplaceSubexpression(const Expression & needle,
1026     const Expression & replace)
1027 {
1028   int ret = 0;
1029   if (!IsLeaf())
1030   {
1031     // recurse
1032     for(int i = 0; i < GetSize(); i++)
1033     {
1034       ret += GetNode(i)->ReplaceSubexpression(needle, replace);
1035     }
1036   }
1037   // act on this node
1038   if (IsEqualTo(needle))
1039   {
1040     ret++;
1041     ReplaceWithExpression(replace);
1042   }
1043   return ret;
1044 }
1045 
ResetVarNames(const std::string & vn,int lid,int uid)1046 void BasicExpression::ResetVarNames(const std::string & vn,
1047                                     int lid,
1048                                     int uid)
1049 {
1050   // set all variable names in the expression to vn
1051   if (!IsLeaf())
1052   {
1053     for(int i = 0; i < GetSize(); i++)
1054     {
1055       GetNode(i)->ResetVarNames(vn, lid, uid);
1056     }
1057   }
1058   else
1059   {
1060     if (GetOpType() == VAR)
1061     {
1062       int vi = GetVarIndex();
1063       if (vi >= lid && vi <= uid)
1064       {
1065         SetVarName(vn);
1066       }
1067     }
1068   }
1069 }
1070 
1071 
DistributeProductsOverSums()1072 bool BasicExpression::DistributeProductsOverSums()
1073 {
1074   // recursive part
1075   bool ret = false;
1076   if (!IsLeaf())
1077   {
1078     for(int i = 0; i < GetSize(); i++)
1079     {
1080       bool haschanged = GetNode(i)->DistributeProductsOverSums();
1081       if (haschanged)
1082       {
1083         ret = true;
1084       }
1085     }
1086   }
1087   // deal with this node
1088   Expression e(0.0);
1089   if (GetOpType() == PRODUCT)
1090   {
1091     for(int i = 0; i < GetSize(); i++)
1092     {
1093       if (GetNode(i)->GetOpType() == SUM)
1094       {
1095         // found occurrence of *(+), distribute
1096         ret = true;
1097         Expression f = (*this) / GetNode(i);
1098         Simplify(&f);
1099         for(int j = 0; j < GetNode(i)->GetSize(); j++)
1100         {
1101           e = e + f * GetNode(i)->GetNode(j);
1102         }
1103         // now replace this with e
1104         ReplaceWithExpression(e);
1105       }
1106     }
1107   }
1108   return ret;
1109 }
1110 
GetVarIndices(std::vector<int> & vidx)1111 void BasicExpression::GetVarIndices(std::vector<int> & vidx)
1112 {
1113   if (!IsLeaf())
1114   {
1115     for(int i = 0; i < GetSize(); i++)
1116     {
1117       GetNode(i)->GetVarIndices(vidx);
1118     }
1119   }
1120   else if (IsVariable())
1121   {
1122     int vi = GetVarIndex();
1123     if (find(vidx.begin(), vidx.end(), vi) == vidx.end())
1124     {
1125       vidx.push_back(vi);
1126     }
1127   }
1128 }
1129 
GetVarIndicesInSchema(std::vector<int> & vidx,const Expression & schema)1130 void BasicExpression::GetVarIndicesInSchema(std::vector<int> & vidx,
1131     const Expression & schema)
1132 {
1133   // recurse
1134   if (!IsLeaf())
1135   {
1136     for(int i = 0; i < GetSize(); i++)
1137     {
1138       GetNode(i)->GetVarIndicesInSchema(vidx, schema);
1139     }
1140   }
1141   // deal with this node
1142   if (IsEqualBySchema(schema))
1143   {
1144     GetVarIndices(vidx);
1145   }
1146 }
1147 
1148 // find the variable name corresponding to variable index vi
FindVariableName(int vi)1149 std::string BasicExpression::FindVariableName(int vi)
1150 {
1151   std::string vn;
1152   if (IsVariable())
1153   {
1154     if (GetVarIndex() == vi)
1155     {
1156       return GetVarName();
1157     }
1158     else
1159     {
1160       return "";
1161     }
1162   }
1163   else
1164   {
1165     int i;
1166     for(i = 0; i < GetSize(); i++)
1167     {
1168       vn = GetNode(i)->FindVariableName(vi);
1169       if (vn.length() > 0)
1170       {
1171         return vn;
1172       }
1173     }
1174   }
1175   return "";
1176 }
1177 
1178 // is this expression linear?
IsLinear() const1179 bool BasicExpression::IsLinear() const
1180 {
1181   if (IsVariable())
1182   {
1183     if (GetExponent() != 0 && GetExponent() != 1)
1184     {
1185       return false;
1186     }
1187     else
1188     {
1189       return true;
1190     }
1191   }
1192   if (IsConstant())
1193   {
1194     return true;
1195   }
1196   if(GetOpType() == SUM || GetOpType() == DIFFERENCE)
1197   {
1198     int i;
1199     for(i = 0; i < GetSize(); i++)
1200     {
1201       if (!GetNode(i)->IsLinear())
1202       {
1203         return false;
1204       }
1205     }
1206     return true;
1207   }
1208   else
1209   {
1210     return false;
1211   }
1212 }
1213 
1214 // is this expression a quadratic product?
IsQuadratic(int & prodtype) const1215 bool BasicExpression::IsQuadratic(int& prodtype) const
1216 {
1217   bool ret = false;
1218   if ((GetOpType() == PRODUCT &&
1219        GetNode(0)->GetOpType() == VAR && GetNode(1)->GetOpType() == VAR) ||
1220       (GetOpType() == POWER &&
1221        GetNode(0)->GetOpType() == VAR && GetNode(1)->GetValue() == 2) ||
1222       (GetOpType() == VAR && GetExponent() == 2))
1223   {
1224     prodtype = GetOpType();
1225     ret = true;
1226   }
1227   return ret;
1228 }
IsQuadratic() const1229 bool BasicExpression::IsQuadratic() const
1230 {
1231   int ret = 0;
1232   return IsQuadratic(ret);
1233 }
1234 
1235 // return info about the linear part (assumes Simplify() has already been
1236 // called on this) - return false if expression has no linear part
1237 // by "linear part" we mean lin(x) in expr(x,y) = lin(x) + nonlin(y)
GetLinearInfo(std::vector<double> & lincoeff,std::vector<int> & linvi,std::vector<std::string> & linvn,double & c)1238 bool BasicExpression::GetLinearInfo(std::vector<double> & lincoeff,
1239                                     std::vector<int> & linvi,
1240                                     std::vector<std::string> & linvn,
1241                                     double& c)
1242 {
1243   c = 0;
1244   bool ret = false;
1245   Expression nl(GetPureNonlinearPart());
1246   if (IsLinear())
1247   {
1248     nl->Zero();
1249   }
1250   if (lincoeff.size() > 0)
1251   {
1252     lincoeff.erase(lincoeff.begin(), lincoeff.end());
1253     linvi.erase(linvi.begin(), linvi.end());
1254     linvn.erase(linvn.begin(), linvn.end());
1255   }
1256   if (IsLeaf())
1257   {
1258     if (IsConstant())
1259     {
1260       // just a constant
1261       c = GetValue();
1262       ret = true;
1263     }
1264     else if (IsVariable() && GetExponent() == 1)
1265     {
1266       // just a variable
1267       linvi.push_back(GetVarIndex());
1268       lincoeff.push_back(GetCoeff());
1269       linvn.push_back(GetVarName());
1270       ret = true;
1271     }
1272   }
1273   else
1274   {
1275     if (GetOpType() == SUM)
1276     {
1277       int i, vi;
1278       c = 0;
1279       for(i = 0; i < GetSize(); i++)
1280       {
1281         if (GetNode(i)->IsConstant())
1282         {
1283           if (i > 0)
1284           {
1285             //std::cerr << "BasicExpression::GetLinearInfo: WARNING: "
1286             //          << "run Simplify() first\n";
1287           }
1288           c += GetNode(i)->GetValue();
1289         }
1290         else if (GetNode(i)->IsVariable() &&
1291                  GetNode(i)->GetExponent() == 1)
1292         {
1293           vi = GetNode(i)->GetVarIndex();
1294           if (!nl->DependsOnVariable(vi))
1295           {
1296             // vi depends only linearly on expression
1297             linvi.push_back(vi);
1298             lincoeff.push_back(GetNode(i)->GetCoeff());
1299             linvn.push_back(GetNode(i)->GetVarName());
1300             ret = true;
1301           }
1302         }
1303       }
1304     }
1305   }
1306   return ret;
1307 }
1308 
1309 // return info about the purely linear part
1310 // (assumes Simplify() has already been
1311 // called on this) - return false if expression has no linear part
1312 // by "pure linear part" we mean e.g. x+y in x+y+y^2
GetPureLinearInfo(std::vector<double> & lincoeff,std::vector<int> & linvi,std::vector<std::string> & linvn,double & c)1313 bool BasicExpression::GetPureLinearInfo(std::vector<double> & lincoeff,
1314                                         std::vector<int> & linvi,
1315                                         std::vector<std::string> & linvn,
1316                                         double& c)
1317 {
1318   c = 0;
1319   bool ret = false;
1320   int i;
1321   Expression nl(GetPureNonlinearPart());
1322   if (IsLinear())
1323   {
1324     nl->Zero();
1325   }
1326   if (lincoeff.size() > 0)
1327   {
1328     lincoeff.erase(lincoeff.begin(), lincoeff.end());
1329     linvi.erase(linvi.begin(), linvi.end());
1330     linvn.erase(linvn.begin(), linvn.end());
1331   }
1332   if (IsLeaf())
1333   {
1334     if (IsConstant())
1335     {
1336       // just a constant
1337       c = GetValue();
1338       ret = true;
1339     }
1340     else if (IsVariable() && GetExponent() == 1)
1341     {
1342       // just a variable
1343       linvi.push_back(GetVarIndex());
1344       lincoeff.push_back(GetCoeff());
1345       linvn.push_back(GetVarName());
1346       ret = true;
1347     }
1348   }
1349   else
1350   {
1351     if (GetOpType() == SUM)
1352     {
1353       int vi;
1354       c = 0;
1355       for(i = 0; i < GetSize(); i++)
1356       {
1357         if (GetNode(i)->IsConstant())
1358         {
1359           if (i > 0)
1360           {
1361             //std::cerr << "BasicExpression::GetLinearInfo: WARNING: "
1362             //          << "run Simplify() first\n";
1363           }
1364           c += GetNode(i)->GetValue();
1365         }
1366         else if (GetNode(i)->IsVariable() &&
1367                  GetNode(i)->GetExponent() == 1)
1368         {
1369           vi = GetNode(i)->GetVarIndex();
1370           linvi.push_back(vi);
1371           lincoeff.push_back(GetNode(i)->GetCoeff());
1372           linvn.push_back(GetNode(i)->GetVarName());
1373           ret = true;
1374         }
1375       }
1376 
1377     }
1378   }
1379   return ret;
1380 }
1381 
1382 // get the linear part - x in x+y+y^2
GetLinearPart()1383 Expression BasicExpression::GetLinearPart()
1384 {
1385   std::vector<double> lincoeff;
1386   std::vector<int> linvi;
1387   std::vector<std::string> linvn;
1388   double c;
1389   GetLinearInfo(lincoeff, linvi, linvn, c);
1390   int i;
1391   Expression ret;
1392   if (lincoeff.size() > 0)
1393   {
1394     ret->SetOpType(VAR);
1395     ret->SetVarIndex(linvi[0]);
1396     ret->SetCoeff(lincoeff[0]);
1397     ret->SetVarName(linvn[0]);
1398     ret->SetExponent(1.0);
1399     if (lincoeff.size() > 1)
1400     {
1401       Expression addend(1.0, -1, NOTVARNAME);
1402       for(i = 1; i < (int) lincoeff.size(); i++)
1403       {
1404         addend->SetVarIndex(linvi[i]);
1405         addend->SetCoeff(lincoeff[i]);
1406         addend->SetVarName(linvn[i]);
1407         ret = ret + addend;
1408       }
1409     }
1410   }
1411   return ret;
1412 }
1413 
1414 // get the pure linar part - x+y in x+y+y^2
GetPureLinearPart()1415 Expression BasicExpression::GetPureLinearPart()
1416 {
1417   std::vector<double> lincoeff;
1418   std::vector<int> linvi;
1419   std::vector<std::string> linvn;
1420   double c;
1421   GetPureLinearInfo(lincoeff, linvi, linvn, c);
1422   int i;
1423   Expression ret(0.0);
1424   if (lincoeff.size() > 0)
1425   {
1426     ret->SetOpType(VAR);
1427     ret->SetVarIndex(linvi[0]);
1428     ret->SetCoeff(lincoeff[0]);
1429     ret->SetVarName(linvn[0]);
1430     ret->SetExponent(1.0);
1431     if (lincoeff.size() > 1)
1432     {
1433       for(i = 1; i < (int) lincoeff.size(); i++)
1434       {
1435         Expression addend(lincoeff[i], linvi[i], linvn[i]);
1436         ret = SumLink(ret, addend);
1437       }
1438     }
1439   }
1440   return ret;
1441 }
1442 
1443 // get the nonlinear part - nonlin(y) in expr(x,y) = lin(x) + nonlin(y)
GetNonlinearPart()1444 Expression BasicExpression::GetNonlinearPart()
1445 {
1446   Expression ret(GetPureNonlinearPart());
1447   std::vector<double> linval;
1448   std::vector<int> linidx;
1449   std::vector<std::string> linvn;
1450   double c = 0;
1451   GetPureLinearInfo(linval, linidx, linvn, c);
1452   int i;
1453   Expression addend(1.0, -1, NOTVARNAME);
1454   // we cycle backwards to keep the order of addends in ret
1455   for(i = linidx.size() - 1; i >= 0 ; i--)
1456   {
1457     if (ret->DependsOnVariable(linidx[i]))
1458     {
1459       // pure nonlinear part depends on varindex i, add it to ret
1460       addend->SetCoeff(linval[i]);
1461       addend->SetVarIndex(linidx[i]);
1462       addend->SetVarName(linvn[i]);
1463       ret = addend + ret;
1464     }
1465   }
1466   return ret;
1467 }
1468 
1469 
1470 // get the purely nonlinear part - e.g. only y^2 in x+y+y^2
GetPureNonlinearPart()1471 Expression BasicExpression::GetPureNonlinearPart()
1472 {
1473   Expression ret(0.0);
1474   if (!IsLeaf())
1475   {
1476     if (GetOpType() == SUM)
1477     {
1478       int i;
1479       for(i = 0; i < GetSize(); i++)
1480       {
1481         if (!GetNode(i)->IsLinear())
1482         {
1483           ret = SumLink(ret, GetNode(i));
1484         }
1485       }
1486     }
1487     else if (GetOpType() == DIFFERENCE)
1488     {
1489       int i;
1490       for(i = 0; i < GetSize(); i++)
1491       {
1492         if (!GetNode(i)->IsLinear())
1493         {
1494           ret = ret - GetNode(i);
1495         }
1496       }
1497     }
1498     else if (GetOpType() == PLUS)
1499     {
1500       ret = GetNode(0);
1501     }
1502     else if (GetOpType() == MINUS)
1503     {
1504       ret = GetNode(0);
1505       ret->SetCoeff(-ret->GetCoeff());
1506     }
1507     else
1508     {
1509       ret = *this;
1510     }
1511   }
1512   else
1513   {
1514     // leaf but can be a power
1515     if (GetExponent() != 0 && GetExponent() != 1)
1516     {
1517       ret = *this;
1518     }
1519   }
1520   return ret;
1521 }
1522 
1523 // get value of additive constant
GetConstantPart()1524 double BasicExpression::GetConstantPart()
1525 {
1526   double ret = 0;
1527   if (IsConstant())
1528   {
1529     ret = GetValue();
1530   }
1531   else if (!IsLeaf())
1532   {
1533     int op = GetOpType();
1534     if (op == SUM || op == DIFFERENCE)
1535     {
1536       int i = 0;
1537       int sz = GetSize();
1538       while(i < sz)
1539       {
1540         if (GetNode(i)->IsConstant())
1541         {
1542           if (op == SUM || (op == DIFFERENCE && i == 0))
1543           {
1544             ret += GetNode(i)->GetValue();
1545           }
1546           else
1547           {
1548             ret -= GetNode(i)->GetValue();
1549           }
1550         }
1551         i++;
1552       }
1553     }
1554   }
1555   return ret;
1556 }
1557 
1558 // doesn't deal with additive constants in PLUS/MINUS operands
RemoveAdditiveConstant()1559 double BasicExpression::RemoveAdditiveConstant()
1560 {
1561   double ret = 0;
1562   if (IsConstant())
1563   {
1564     ret = GetValue();
1565     SetValue(0);
1566   }
1567   else if (!IsLeaf())
1568   {
1569     int op = GetOpType();
1570     if (op == SUM || op == DIFFERENCE)
1571     {
1572       int i = 0;
1573       int sz = GetSize();
1574       while(i < sz)
1575       {
1576         if (GetNode(i)->IsConstant())
1577         {
1578           if (op == SUM || (op == DIFFERENCE && i == 0))
1579           {
1580             ret += GetNode(i)->GetValue();
1581           }
1582           else
1583           {
1584             ret -= GetNode(i)->GetValue();
1585           }
1586           DeleteNode(i);
1587           sz--;
1588         }
1589         else
1590         {
1591           i++;
1592         }
1593       }
1594     }
1595   }
1596   return ret;
1597 }
1598 
1599 /************** expression creation (no change to args) ***************/
1600 
1601 // BIG FAT WARNING: when you change these operators, also please
1602 // change their "-Link" counterparts!
1603 
1604 // sums:
operator +(Expression a,Expression b)1605 Expression operator + (Expression a,
1606                        Expression b)
1607 {
1608   Expression ret;
1609   // make a preliminary check
1610   if (a->GetCoeff() == 0 || a->HasValue(0))
1611   {
1612     ret.SetToCopyOf(b);
1613     return ret;
1614   }
1615   if (b->GetCoeff() == 0 || b->HasValue(0))
1616   {
1617     ret.SetToCopyOf(a);
1618     return ret;
1619   }
1620   if (!(a->IsConstant() && b->IsConstant()) && a->IsEqualToNoCoeff(b))
1621   {
1622     a->SetCoeff(a->GetCoeff() + b->GetCoeff());
1623     if (std::abs(a->GetCoeff()) < Ev3NearZero())
1624     {
1625       // simplify to zero - for differences
1626       Expression zero(0.0);
1627       return zero;
1628     }
1629     else
1630     {
1631       ret.SetToCopyOf(a);
1632       return ret;
1633     }
1634   }
1635   // go for it
1636   if (a->IsLeaf() && a->GetOpType() == CONST &&
1637       b->IsLeaf() && b->GetOpType() == CONST)
1638   {
1639     // a, b are numbers - add them
1640     ret.SetToCopyOf(a);
1641     ret->SetValue(a->GetValue() + b->GetValue());
1642     ret->SetCoeff(1.0);
1643     ret->SetExponent(1.0);
1644     return ret;
1645   }
1646   else if (a->IsLeaf() && a->GetOpType() == VAR &&
1647            b->IsLeaf() && b->GetOpType() == VAR &&
1648            a->GetVarIndex() == b->GetVarIndex() &&
1649            a->GetExponent() == b->GetExponent())
1650   {
1651     // a, b are the same variable - add coefficients
1652     ret.SetToCopyOf(a);
1653     ret->SetCoeff(a->GetCoeff() + b->GetCoeff());
1654     return ret;
1655   }
1656   else if (a->GetOpType() == SUM && b->GetOpType() != SUM)
1657   {
1658     // a is a sum and b isn't - just add the term b
1659     ret.SetToCopyOf(a);
1660     ret->DistributeCoeffOverSum();
1661     Int i = 0;
1662     bool couldsimplify = false;
1663     Expression tmp;
1664     // if t is a leaf and there is a like leaf in this,
1665     // just add it to the value/coefficient
1666     if (b->IsLeaf() && b->GetOpType() == CONST)
1667     {
1668       // b is a constant
1669       for (i = 0; i < ret->GetSize(); i++)
1670       {
1671         tmp = ret->GetNode(i);
1672         if (tmp->IsLeaf() && tmp->GetOpType() == CONST)
1673         {
1674           tmp->SetValue(tmp->GetValue() + b->GetValue() / ret->GetCoeff());
1675           tmp->SetCoeff(1.0);
1676           tmp->SetExponent(1.0); // NB: changing tmp should also change a
1677           couldsimplify = true;
1678           break;
1679         }
1680       }
1681     }
1682     else if (b->IsLeaf() && b->GetOpType() == VAR)
1683     {
1684       // b is a variable
1685       for (i = 0; i < ret->GetSize(); i++)
1686       {
1687         if (ret->GetNode(i)->IsLeaf() && ret->GetNode(i)->GetOpType() == VAR &&
1688             b->GetVarIndex() == ret->GetNode(i)->GetVarIndex() &&
1689             b->GetExponent() == ret->GetNode(i)->GetExponent())
1690         {
1691           double tc = ret->GetNode(i)->GetCoeff() +
1692                       b->GetCoeff() / ret->GetCoeff();
1693           // warning: tc could be zero, but it would be cumbersome
1694           // to simplify it here - do it in SimplifyConstant
1695           ret->GetNode(i)->SetCoeff(tc);
1696           couldsimplify = true;
1697           break;
1698         }
1699       }
1700     }
1701     else if (!b->IsLeaf())
1702     {
1703       // a is a sum, b is a nonleaf, look for a subnode of a similar to b
1704       for (i = 0; i < ret->GetSize(); i++)
1705       {
1706         if (ret->GetNode(i)->IsEqualTo(b))
1707         {
1708           // found one, add coefficients - notice, as above, coeff could
1709           // be zero, but deal with that case in SimplifyConstant
1710           ret->GetNode(i)->SetCoeff(ret->GetNode(i)->GetCoeff()
1711                                     + b->GetCoeff());
1712           couldsimplify = true;
1713           break;
1714         }
1715       }
1716     }
1717     if (!couldsimplify)
1718     {
1719       // either could not simplify in steps above, or b is an operator
1720       ret->AddCopyOfNode(b);
1721     }
1722     return ret;
1723   }
1724   else if (a->GetOpType() == SUM && b->GetOpType() == SUM)
1725   {
1726     // a, b are sums - add terms of b to a
1727     b->DistributeCoeffOverSum();
1728     ret.SetToCopyOf(a);
1729     Int i = 0;
1730     Int s = b->GetSize();
1731     for (i = 0; i < s; i++)
1732     {
1733       ret = ret + b->GetNode(i);
1734     }
1735     return ret;
1736   }
1737   else if (a->GetOpType() != SUM && b->GetOpType() == SUM)
1738   {
1739     // a is not a sum but b is - transform this into a sum
1740     ret.SetToCopyOf(b);
1741     ret = ret + a;
1742     return ret;
1743   }
1744   else
1745   {
1746     // all other cases - make new node on top of the addends
1747     ret->SetOpType(SUM);
1748     ret->SetCoeff(1.0);
1749     ret->SetExponent(1.0);
1750     ret->AddCopyOfNode(a);
1751     ret->AddCopyOfNode(b);
1752     return ret;
1753   }
1754 }
1755 
1756 
1757 // product
operator *(Expression a,Expression t)1758 Expression operator * (Expression a,
1759                        Expression t)
1760 {
1761   Expression ret;
1762   // make a preliminary check
1763   if (a->GetCoeff() == 0 || t->GetCoeff() == 0 ||
1764       a->HasValue(0) || t->HasValue(0))
1765   {
1766     Expression zero(0.0);
1767     return zero;
1768   }
1769   if (a->HasValue(1))
1770   {
1771     return t;
1772   }
1773   if (t->HasValue(1))
1774   {
1775     return a;
1776   }
1777   if (!(a->IsConstant() && t->IsConstant()) && a->IsEqualToNoCoeff(t))
1778   {
1779     Expression two(2.0);
1780     ret.SetToCopyOf(a);
1781     ret->SetCoeff(1.0);
1782     ret = ret ^ two;
1783     ret->SetCoeff(a->GetCoeff() * t->GetCoeff());
1784     return ret;
1785   }
1786   // go for it
1787   if (a->IsLeaf() && a->GetOpType() == CONST &&
1788       t->IsLeaf() && t->GetOpType() == CONST)
1789   {
1790     // a, t are numbers - multiply them
1791     ret.SetToCopyOf(a);
1792     ret->SetValue(a->GetValue() * t->GetValue());
1793     ret->SetCoeff(1.0);
1794     ret->SetExponent(1.0);
1795     return ret;
1796   }
1797   else if (a->IsLeaf() && a->GetOpType() == VAR &&
1798            t->IsLeaf() && t->GetOpType() == VAR &&
1799            a->GetVarIndex() == t->GetVarIndex())
1800   {
1801     // a, t are the same variable - multiply coefficients
1802     // and add exponents
1803     ret.SetToCopyOf(a);
1804     ret->SetCoeff(a->GetCoeff() * t->GetCoeff());
1805     ret->SetExponent(a->GetExponent() + t->GetExponent());
1806     return ret;
1807   }
1808   else if (t->IsConstant())
1809   {
1810     // t is constant, set coeff of a
1811     ret.SetToCopyOf(a);
1812     ret->SetCoeff(a->GetCoeff() * t->GetValue());
1813     ret->DistributeCoeffOverSum();
1814     return ret;
1815   }
1816   else if (a->IsConstant())
1817   {
1818     // a is constant, set coeff of t
1819     ret.SetToCopyOf(t);
1820     ret->SetCoeff(t->GetCoeff() * a->GetValue());
1821     ret->DistributeCoeffOverSum();
1822     return ret;
1823   }
1824   else if (a->GetOpType() == PRODUCT && t->GetOpType() != PRODUCT)
1825   {
1826     // a is a product and t isn't - just multiply the term t
1827     ret.SetToCopyOf(a);
1828     Int i = 0;
1829     bool couldsimplify = false;
1830     if (t->IsLeaf() && t->GetOpType() == VAR)
1831     {
1832       // t is a variable
1833       Expression tmp;
1834       for (i = 0; i < ret->GetSize(); i++)
1835       {
1836         tmp = ret->GetNode(i);
1837         if (tmp->IsLeaf() && tmp->GetOpType() == VAR &&
1838             t->GetVarIndex() == tmp->GetVarIndex())
1839         {
1840           // found same variable in a, multiply coeffs and add exponents
1841           tmp->SetCoeff(tmp->GetCoeff() * t->GetCoeff());
1842           tmp->SetExponent(tmp->GetExponent() + t->GetExponent());
1843           couldsimplify = true;
1844           break;
1845         }
1846       }
1847     }
1848     // here we shan't try to simplify f*f <-- f^2 (f nonleaf)
1849     // because a product of nonleaves is easier to manipulate than
1850     // a power (as it adds a depth level)
1851     if (!couldsimplify)
1852     {
1853       // either could not simplify in steps above, or t is an operator
1854       ret->AddCopyOfNode(t);
1855     }
1856     return ret;
1857   }
1858   else if (a->GetOpType() == PRODUCT && t->GetOpType() == PRODUCT)
1859   {
1860     // a, t are products - multiply terms of t to a
1861     t->DistributeCoeffOverProduct();
1862     ret.SetToCopyOf(a);
1863     Int s = t->GetSize();
1864     for (Int i = 0; i < s; i++)
1865     {
1866       ret = ret * t->GetNode(i);
1867     }
1868     return ret;
1869   }
1870   else if (a->GetOpType() != PRODUCT && t->GetOpType() == PRODUCT)
1871   {
1872     // a is not a products but t is - transform this into a product
1873     ret.SetToCopyOf(t);
1874     ret = ret * a;
1875     return ret;
1876   }
1877   else
1878   {
1879     // all other cases - make new node on top of the addends
1880     ret->SetCoeff(1.0);
1881     ret->SetExponent(1.0);
1882     ret->SetOpType(PRODUCT);
1883     ret->AddCopyOfNode(a);
1884     ret->AddCopyOfNode(t);
1885     return ret;
1886   }
1887 }
1888 
1889 // fractions:
operator /(Expression a,Expression t)1890 Expression operator / (Expression a,
1891                        Expression t)
1892 {
1893   Expression ret;
1894   // make a preliminary check
1895   if (t->GetCoeff() == 0)
1896   {
1897     // divide by zero
1898     unsigned long mycode(0);
1899     std::string myif("Expression Building");
1900     std::string myscope("operator/");
1901     std::string myop("t.GetCoeff()==0");
1902     std::string mydesc("Divisor cannot be zero");
1903     std::string myinfo(HELPURL);
1904     std::string mydiv(NONE);
1905     throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
1906   }
1907   if (a->GetCoeff() == 0 || a->HasValue(0))
1908   {
1909     // dividend has zero coeff, return zero
1910     Expression zero(0.0);
1911     return zero;
1912   }
1913   if (t->HasValue(1))
1914   {
1915     ret.SetToCopyOf(a);
1916     return ret;
1917   }
1918   if (!(a->IsConstant() && t->IsConstant()) && a->IsEqualToNoCoeff(t))
1919   {
1920     // dividend = divisor, return ratio of coefficients
1921     Expression one(1.0);
1922     one->SetCoeff(a->GetCoeff() / t->GetCoeff());
1923     return one;
1924   }
1925   // go for it
1926   if (a->IsLeaf() && a->GetOpType() == CONST &&
1927       t->IsLeaf() && t->GetOpType() == CONST)
1928   {
1929     // a, t are numbers - divide them
1930     if (t->GetValue() == 0)
1931     {
1932       unsigned long mycode(0);
1933       std::string myif("Expression Building");
1934       std::string myscope("operator/");
1935       std::string myop("t.GetValue()==0");
1936       std::string mydesc("Divisor cannot be zero");
1937       std::string myinfo(HELPURL);
1938       std::string mydiv(NONE);
1939       throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
1940     }
1941     else
1942     {
1943       ret.SetToCopyOf(a);
1944       ret->SetValue(a->GetValue() / t->GetValue());
1945       ret->SetCoeff(1.0);
1946       ret->SetExponent(1.0);
1947       return ret;
1948     }
1949   }
1950   else if (t->HasValue(1))
1951   {
1952     // divide by constant 1, don't do anything
1953     ret.SetToCopyOf(a);
1954     return ret;
1955   }
1956   else if (t->IsConstant())
1957   {
1958     // t is constant, set coeff of a
1959     ret.SetToCopyOf(a);
1960     ret->SetCoeff(a->GetCoeff() / t->GetValue());
1961     ret->DistributeCoeffOverSum();
1962     return ret;
1963   }
1964   else if (a->IsVariable() && t->IsVariable() &&
1965            a->GetVarIndex() == t->GetVarIndex())
1966   {
1967     // cx^e / dx^f = (c/d)x^(e-f)
1968     ret.SetToCopyOf(a);
1969     double te = a->GetExponent() - t->GetExponent();
1970     double tc = a->GetCoeff() / t->GetCoeff();
1971     if (std::abs(te) < Ev3NearZero())
1972     {
1973       Expression c(tc);
1974       return c;
1975     }
1976     ret->SetCoeff(tc);
1977     ret->SetExponent(te);
1978     return ret;
1979   }
1980   else if (a->IsVariable() && t->GetOpType() == PRODUCT)
1981   {
1982     // a is a variable, t is a product - see if a appears in t
1983     // and cancel common term
1984     // first simplify coeffs of divisor
1985     Expression at;
1986     at.SetToCopyOf(a);
1987     ret.SetToCopyOf(t);
1988     ret->ConsolidateProductCoeffs();
1989     // denominator
1990     if (std::abs(ret->GetCoeff()) < Ev3NearZero())
1991     {
1992       // divide by zero
1993       unsigned long mycode(22);
1994       std::string myif("Expression Building");
1995       std::string myscope("operator/");
1996       std::string myop("t->GetCoeff()");
1997       std::string mydesc("Divisor cannot be zero");
1998       std::string myinfo(HELPURL);
1999       std::string mydiv(NONE);
2000       throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
2001     }
2002     if (std::abs(at->GetCoeff()) < Ev3NearZero())
2003     {
2004       Expression zero(0.0);
2005       return zero;
2006     }
2007     double accumulatedcoeff = at->GetCoeff() / ret->GetCoeff();
2008     at->SetCoeff(1.0);
2009     ret->SetCoeff(1.0);
2010     // now try simplification
2011     Int i;
2012     for (i = 0; i < ret->GetSize(); i++)
2013     {
2014       if (ret->GetNode(i)->GetOpType() == VAR &&
2015           at->GetVarIndex() == ret->GetNode(i)->GetVarIndex())
2016       {
2017         double te = at->GetExponent() - ret->GetNode(i)->GetExponent();
2018         if (std::abs(te) < Ev3NearZero())
2019         {
2020           // exponents are the same, just cancel
2021           at->One();
2022           ret->DeleteNode(i);
2023         }
2024         else if (te > 0)
2025         {
2026           // numerator remains, cancel denominator
2027           at->SetExponent(te);
2028           ret->DeleteNode(i);
2029         }
2030         else if (te < 0)
2031         {
2032           // numerator goes to one, denominator remains
2033           at->One();
2034           ret->GetNode(i)->SetExponent(-te);
2035         }
2036         // exit loop
2037         break;
2038       }
2039     }
2040     // check that denominator (t) has more than one operand;
2041     // if not, bring up a rank level
2042     if (ret->GetSize() == 1)
2043     {
2044       ret = ret->GetNode(0);
2045     }
2046     // build ratio
2047     Expression ret2;
2048     ret2->SetOpType(FRACTION);
2049     ret2->SetCoeff(accumulatedcoeff);
2050     ret2->SetExponent(1.0);
2051     ret2->AddCopyOfNode(at);
2052     ret2->AddCopyOfNode(ret);
2053     return ret2;
2054   }
2055   else if (t->IsVariable() && a->GetOpType() == PRODUCT)
2056   {
2057     // t is a variable, a is a product - see if t appears in a
2058     // and cancel common term
2059     // first simplify coeffs of divisor
2060     Expression bt;
2061     bt.SetToCopyOf(t);
2062     ret.SetToCopyOf(a);
2063     ret->ConsolidateProductCoeffs();
2064     // denominator - already checked
2065     if (std::abs(ret->GetCoeff()) < Ev3NearZero())
2066     {
2067       Expression zero(0.0);
2068       return zero;
2069     }
2070     double accumulatedcoeff = ret->GetCoeff() / bt->GetCoeff();
2071     ret->SetCoeff(1.0);
2072     bt->SetCoeff(1.0);
2073     // now try simplification
2074     Int i;
2075     for (i = 0; i < ret->GetSize(); i++)
2076     {
2077       if (ret->GetNode(i)->GetOpType() == VAR &&
2078           bt->GetVarIndex() == ret->GetNode(i)->GetVarIndex())
2079       {
2080         double te = ret->GetNode(i)->GetExponent() - bt->GetExponent();
2081         if (std::abs(te) < Ev3NearZero())
2082         {
2083           // exponents are the same, just cancel
2084           bt->One();
2085           ret->DeleteNode(i);
2086         }
2087         else if (te > 0)
2088         {
2089           // numerator remains, cancel denominator
2090           bt->One();
2091           ret->GetNode(i)->SetExponent(te);
2092         }
2093         else if (te < 0)
2094         {
2095           // numerator goes to one, denominator remains
2096           bt->SetExponent(-te);
2097           ret->DeleteNode(i);
2098         }
2099         // exit loop
2100         break;
2101       }
2102     }
2103     // check that numerator (a) has more than one operands;
2104     // if not, bring up a rank level
2105     if (ret->GetSize() == 1)
2106     {
2107       ret = ret->GetNode(0);
2108     }
2109     // build ratio
2110     Expression ret2;
2111     ret2->SetOpType(FRACTION);
2112     ret2->SetCoeff(accumulatedcoeff);
2113     ret2->SetExponent(1.0);
2114     ret2->AddCopyOfNode(ret);
2115     ret2->AddCopyOfNode(bt);
2116     return ret2;
2117   }
2118   else if (a->GetOpType() == PRODUCT && t->GetOpType() == PRODUCT)
2119   {
2120     // a, t are products, try to cancel common terms
2121     Expression at;
2122     Expression bt;
2123     at.SetToCopyOf(a);
2124     bt.SetToCopyOf(t);
2125     Int i = 0, j = 0;
2126     double accumulatedcoeff;
2127     // first simplify coefficients of operands
2128     at->ConsolidateProductCoeffs();
2129     bt->ConsolidateProductCoeffs();
2130     // denominator
2131     if (std::abs(bt->GetCoeff()) < Ev3NearZero())
2132     {
2133       // divide by zero
2134       unsigned long mycode(21);
2135       std::string myif("Expression Building");
2136       std::string myscope("operator/");
2137       std::string myop("t->GetCoeff()");
2138       std::string mydesc("Divisor cannot be zero");
2139       std::string myinfo(HELPURL);
2140       std::string mydiv(NONE);
2141       throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
2142     }
2143     if (std::abs(at->GetCoeff()) < Ev3NearZero())
2144     {
2145       Expression zero(0.0);
2146       return zero;
2147     }
2148     // save ratio of coeffs of products
2149     accumulatedcoeff = at->GetCoeff() / bt->GetCoeff();
2150     at->SetCoeff(1.0);
2151     bt->SetCoeff(1.0);
2152     // now try simplification
2153     i = 0;
2154     bool isnumeratorempty = false;
2155     bool isdenominatorempty = false;
2156     int szi = at->GetSize();
2157     int szj = bt->GetSize();
2158     while(!isnumeratorempty && !isdenominatorempty && i < szi)
2159     {
2160       j = 0;
2161       while(!isnumeratorempty && !isdenominatorempty && j < szj)
2162       {
2163         if (at->GetNode(i)->IsEqualTo(bt->GetNode(j)))
2164         {
2165           // found like terms i and j
2166           at->DeleteNode(i);
2167           szi--;
2168           if(szi == 0)
2169           {
2170             isnumeratorempty = true;
2171             at->One();
2172           }
2173           bt->DeleteNode(j);
2174           szj--;
2175           if (szj == 0)
2176           {
2177             isdenominatorempty = true;
2178             bt->One();
2179           }
2180           i--;   // cancel the effect of the later i++
2181           break; // go to outer cycle
2182         }
2183         else
2184         {
2185           j++;
2186         }
2187       }
2188       i++;
2189     }
2190     if (bt->HasValue(1))
2191     {
2192       // denominator is 1, return a
2193       at->SetCoeff(accumulatedcoeff);
2194       return at;
2195     }
2196     // now construct fraction
2197     // check that numerator, denominator have more than one operands;
2198     // if not, bring up a rank level
2199     if (at->GetSize() == 1)
2200     {
2201       at = at->GetNode(0);
2202     }
2203     if (bt->GetSize() == 1)
2204     {
2205       bt = bt->GetNode(0);
2206     }
2207     ret->SetCoeff(accumulatedcoeff); // already contains coeffs of a, t
2208     ret->SetExponent(1.0);
2209     ret->SetOpType(FRACTION);
2210     ret->AddCopyOfNode(at);
2211     ret->AddCopyOfNode(bt);
2212     return ret;
2213   }
2214   else
2215   {
2216     Expression at;
2217     Expression bt;
2218     at.SetToCopyOf(a);
2219     bt.SetToCopyOf(t);
2220     ret->SetCoeff(at->GetCoeff() / bt->GetCoeff());
2221     at->SetCoeff(1.0);
2222     bt->SetCoeff(1.0);
2223     ret->SetExponent(1.0);
2224     ret->SetOpType(FRACTION);
2225     ret->AddCopyOfNode(at);
2226     ret->AddCopyOfNode(bt);
2227     return ret;
2228   }
2229 }
2230 
2231 // unary minus:
operator -(Expression a)2232 Expression operator - (Expression a)
2233 {
2234   Expression ret;
2235   ret.SetToCopyOf(a);
2236   if (ret->IsLeaf() && ret->GetOpType() == CONST)
2237   {
2238     ret->SetValue(- ret->GetValue());
2239     ret->SetCoeff(1.0);
2240     ret->SetExponent(1.0);
2241   }
2242   else
2243   {
2244     ret->SetCoeff(- ret->GetCoeff());
2245   }
2246   return ret;
2247 }
2248 
2249 // binary minus:
operator -(Expression a,Expression b)2250 Expression operator - (Expression a,
2251                        Expression b)
2252 {
2253   Expression ret;
2254   if (a->HasValue(0))
2255     return -b;
2256   if (b->HasValue(0))
2257   {
2258     ret.SetToCopyOf(a);
2259     return a;
2260   }
2261   ret = a + (-b);
2262   return ret;
2263 }
2264 
2265 // power:
operator ^(Expression a,Expression t)2266 Expression operator ^ (Expression a,
2267                        Expression t)
2268 {
2269   // make a preliminary check
2270   Expression ret;
2271   if (a->GetCoeff() == 0)
2272   {
2273     // *this is zero, just return zero
2274     Expression zero(0.0);
2275     return zero;
2276   }
2277   if (t->HasValue(0.0))
2278   {
2279     // exponent is 0, just return 1
2280     Expression one(1.0);
2281     return one;
2282   }
2283   else if (t->HasValue(1.0))
2284   {
2285     // exponent is 1, just return a
2286     ret.SetToCopyOf(a);
2287     return ret;
2288   }
2289   if (a->HasValue(0.0))
2290   {
2291     // base is zero, return 0
2292     Expression zero(0.0);
2293     return zero;
2294   }
2295   else if (a->HasValue(1.0))
2296   {
2297     // base is one, return 1
2298     Expression one(1.0);
2299     return one;
2300   }
2301   // go for it
2302   if (a->IsLeaf() && a->GetOpType() == CONST &&
2303       t->IsLeaf() && t->GetOpType() == CONST)
2304   {
2305     // constant to constant
2306     ret.SetToCopyOf(a);
2307     ret->SetValue(pow(ret->GetValue(), t->GetValue()));
2308     ret->SetCoeff(1.0);
2309     ret->SetExponent(1.0);
2310     return ret;
2311   }
2312   else if (a->IsLeaf() && a->GetOpType() == VAR &&
2313            t->IsLeaf() && t->GetOpType() == CONST)
2314   {
2315     // variable to constant
2316     ret.SetToCopyOf(a);
2317     ret->SetCoeff(pow(ret->GetCoeff(), t->GetValue()));
2318     ret->SetExponent(ret->GetExponent() * t->GetValue());
2319     return ret;
2320   }
2321   else
2322   {
2323     ret->SetCoeff(1.0);
2324     ret->SetExponent(1.0);
2325     ret->SetOpType(POWER);
2326     ret->AddCopyOfNode(a);
2327     ret->AddCopyOfNode(t);
2328     return ret;
2329   }
2330 }
2331 
Sin(Expression a)2332 Expression Sin(Expression a)
2333 {
2334   // go for it
2335   if (a->IsLeaf() && a->GetOpType() == CONST)
2336   {
2337     Expression ret;
2338     ret.SetToCopyOf(a);
2339     ret->SetCoeff(1.0);
2340     ret->SetValue(sin(a->GetValue()));
2341     ret->SetExponent(1.0);
2342     ret->SetOpType(CONST);
2343     return ret;
2344   }
2345   else
2346   {
2347     Expression ret;
2348     ret->SetCoeff(1.0);
2349     ret->SetExponent(1.0);
2350     ret->SetOpType(SIN);
2351     ret->AddCopyOfNode(a);
2352     return ret;
2353   }
2354 }
2355 
Cos(Expression a)2356 Expression Cos(Expression a)
2357 {
2358   // go for it
2359   if (a->IsLeaf() && a->GetOpType() == CONST)
2360   {
2361     Expression ret;
2362     ret.SetToCopyOf(a);
2363     ret->SetCoeff(1.0);
2364     ret->SetValue(cos(a->GetValue()));
2365     ret->SetExponent(1.0);
2366     ret->SetOpType(CONST);
2367     return ret;
2368   }
2369   else
2370   {
2371     Expression ret;
2372     ret->SetCoeff(1.0);
2373     ret->SetExponent(1.0);
2374     ret->SetOpType(COS);
2375     ret->AddCopyOfNode(a);
2376     return ret;
2377   }
2378 }
2379 
Tan(Expression a)2380 Expression Tan(Expression a)
2381 {
2382   // go for it
2383   if (a->IsLeaf() && a->GetOpType() == CONST)
2384   {
2385     Expression ret;
2386     ret.SetToCopyOf(a);
2387     ret->SetCoeff(1.0);
2388     ret->SetValue(tan(a->GetValue()));
2389     ret->SetExponent(1.0);
2390     ret->SetOpType(CONST);
2391     return ret;
2392   }
2393   else
2394   {
2395     Expression ret;
2396     ret->SetCoeff(1.0);
2397     ret->SetExponent(1.0);
2398     ret->SetOpType(TAN);
2399     ret->AddCopyOfNode(a);
2400     return ret;
2401   }
2402 }
2403 
Asin(Expression a)2404 Expression Asin(Expression a)
2405 {
2406   // go for it
2407   if (a->IsLeaf() && a->GetOpType() == CONST)
2408   {
2409     Expression ret;
2410     ret.SetToCopyOf(a);
2411     ret->SetCoeff(1.0);
2412     ret->SetValue(asin(a->GetValue()));
2413     ret->SetExponent(1.0);
2414     ret->SetOpType(CONST);
2415     return ret;
2416   }
2417   else
2418   {
2419     Expression ret;
2420     ret->SetCoeff(1.0);
2421     ret->SetExponent(1.0);
2422     ret->SetOpType(ASIN);
2423     ret->AddCopyOfNode(a);
2424     return ret;
2425   }
2426 }
2427 
Acos(Expression a)2428 Expression Acos(Expression a)
2429 {
2430   // go for it
2431   if (a->IsLeaf() && a->GetOpType() == CONST)
2432   {
2433     Expression ret;
2434     ret.SetToCopyOf(a);
2435     ret->SetCoeff(1.0);
2436     ret->SetValue(acos(a->GetValue()));
2437     ret->SetExponent(1.0);
2438     ret->SetOpType(CONST);
2439     return ret;
2440   }
2441   else
2442   {
2443     Expression ret;
2444     ret->SetCoeff(1.0);
2445     ret->SetExponent(1.0);
2446     ret->SetOpType(ACOS);
2447     ret->AddCopyOfNode(a);
2448     return ret;
2449   }
2450 }
2451 
Atan(Expression a)2452 Expression Atan(Expression a)
2453 {
2454   // go for it
2455   if (a->IsLeaf() && a->GetOpType() == CONST)
2456   {
2457     Expression ret;
2458     ret.SetToCopyOf(a);
2459     ret->SetCoeff(1.0);
2460     ret->SetValue(atan(a->GetValue()));
2461     ret->SetExponent(1.0);
2462     ret->SetOpType(CONST);
2463     return ret;
2464   }
2465   else
2466   {
2467     Expression ret;
2468     ret->SetCoeff(1.0);
2469     ret->SetExponent(1.0);
2470     ret->SetOpType(ATAN);
2471     ret->AddCopyOfNode(a);
2472     return ret;
2473   }
2474 }
2475 
Sinh(Expression a)2476 Expression Sinh(Expression a)
2477 {
2478   // go for it
2479   if (a->IsLeaf() && a->GetOpType() == CONST)
2480   {
2481     Expression ret;
2482     ret.SetToCopyOf(a);
2483     ret->SetCoeff(1.0);
2484     ret->SetValue(sinh(a->GetValue()));
2485     ret->SetExponent(1.0);
2486     ret->SetOpType(CONST);
2487     return ret;
2488   }
2489   else
2490   {
2491     Expression ret;
2492     ret->SetCoeff(1.0);
2493     ret->SetExponent(1.0);
2494     ret->SetOpType(SINH);
2495     ret->AddCopyOfNode(a);
2496     return ret;
2497   }
2498 }
2499 
Cosh(Expression a)2500 Expression Cosh(Expression a)
2501 {
2502   // go for it
2503   if (a->IsLeaf() && a->GetOpType() == CONST)
2504   {
2505     Expression ret;
2506     ret.SetToCopyOf(a);
2507     ret->SetCoeff(1.0);
2508     ret->SetValue(cosh(a->GetValue()));
2509     ret->SetExponent(1.0);
2510     ret->SetOpType(CONST);
2511     return ret;
2512   }
2513   else
2514   {
2515     Expression ret;
2516     ret->SetCoeff(1.0);
2517     ret->SetExponent(1.0);
2518     ret->SetOpType(COSH);
2519     ret->AddCopyOfNode(a);
2520     return ret;
2521   }
2522 }
2523 
Tanh(Expression a)2524 Expression Tanh(Expression a)
2525 {
2526   // go for it
2527   if (a->IsLeaf() && a->GetOpType() == CONST)
2528   {
2529     Expression ret;
2530     ret.SetToCopyOf(a);
2531     ret->SetCoeff(1.0);
2532     ret->SetValue(tanh(a->GetValue()));
2533     ret->SetExponent(1.0);
2534     ret->SetOpType(CONST);
2535     return ret;
2536   }
2537   else
2538   {
2539     Expression ret;
2540     ret->SetCoeff(1.0);
2541     ret->SetExponent(1.0);
2542     ret->SetOpType(TANH);
2543     ret->AddCopyOfNode(a);
2544     return ret;
2545   }
2546 }
2547 
Asinh(Expression a)2548 Expression Asinh(Expression a)
2549 {
2550   // go for it
2551   if (a->IsLeaf() && a->GetOpType() == CONST)
2552   {
2553     Expression ret;
2554     ret.SetToCopyOf(a);
2555     ret->SetCoeff(1.0);
2556     ret->SetValue(asinh(a->GetValue()));
2557     ret->SetExponent(1.0);
2558     ret->SetOpType(CONST);
2559     return ret;
2560   }
2561   else
2562   {
2563     Expression ret;
2564     ret->SetCoeff(1.0);
2565     ret->SetExponent(1.0);
2566     ret->SetOpType(ASINH);
2567     ret->AddCopyOfNode(a);
2568     return ret;
2569   }
2570 }
2571 
Acosh(Expression a)2572 Expression Acosh(Expression a)
2573 {
2574   // go for it
2575   if (a->IsLeaf() && a->GetOpType() == CONST)
2576   {
2577     Expression ret;
2578     ret.SetToCopyOf(a);
2579     ret->SetCoeff(1.0);
2580     ret->SetValue(acosh(a->GetValue()));
2581     ret->SetExponent(1.0);
2582     ret->SetOpType(CONST);
2583     return ret;
2584   }
2585   else
2586   {
2587     Expression ret;
2588     ret->SetCoeff(1.0);
2589     ret->SetExponent(1.0);
2590     ret->SetOpType(ACOSH);
2591     ret->AddCopyOfNode(a);
2592     return ret;
2593   }
2594 }
2595 
Atanh(Expression a)2596 Expression Atanh(Expression a)
2597 {
2598   // go for it
2599   if (a->IsLeaf() && a->GetOpType() == CONST)
2600   {
2601     Expression ret;
2602     ret.SetToCopyOf(a);
2603     ret->SetCoeff(1.0);
2604     ret->SetValue(atanh(a->GetValue()));
2605     ret->SetExponent(1.0);
2606     ret->SetOpType(CONST);
2607     return ret;
2608   }
2609   else
2610   {
2611     Expression ret;
2612     ret->SetCoeff(1.0);
2613     ret->SetExponent(1.0);
2614     ret->SetOpType(ATANH);
2615     ret->AddCopyOfNode(a);
2616     return ret;
2617   }
2618 }
2619 
Log2(Expression a)2620 Expression Log2(Expression a)
2621 {
2622   // make a preliminary check
2623   if (a->IsZero())
2624   {
2625     // *this is zero, can't do
2626     unsigned long mycode(0);
2627     std::string myif("Expression Building");
2628     std::string myscope("Log2");
2629     std::string myop("IsZero()");
2630     std::string mydesc("log2(0) is undefined");
2631     std::string myinfo(HELPURL);
2632     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2633   }
2634   if (a->IsLessThan(0))
2635   {
2636     // argument is < zero, can't do
2637     unsigned long mycode(0);
2638     std::string myif("Expression Building");
2639     std::string myscope("Log2");
2640     std::string myop("value <= 0");
2641     std::string mydesc("log2(<=0) is undefined");
2642     std::string myinfo(HELPURL);
2643     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2644   }
2645   // go for it
2646   if (a->IsLeaf() && a->GetOpType() == CONST)
2647   {
2648     Expression ret;
2649     ret.SetToCopyOf(a);
2650     double t = ret->GetValue();
2651     assert(t >= 0);
2652     ret->SetCoeff(1.0);
2653     ret->SetValue(log2(t));
2654     ret->SetExponent(1.0);
2655     ret->SetOpType(CONST);
2656     return ret;
2657   }
2658   else
2659   {
2660     Expression ret;
2661     ret->SetCoeff(1.0);
2662     ret->SetExponent(1.0);
2663     ret->SetOpType(LOG2);
2664     ret->AddCopyOfNode(a);
2665     return ret;
2666   }
2667 }
2668 
Log10(Expression a)2669 Expression Log10(Expression a)
2670 {
2671   // make a preliminary check
2672   if (a->IsZero())
2673   {
2674     // *this is zero, can't do
2675     unsigned long mycode(0);
2676     std::string myif("Expression Building");
2677     std::string myscope("Log10");
2678     std::string myop("IsZero()");
2679     std::string mydesc("log10(0) is undefined");
2680     std::string myinfo(HELPURL);
2681     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2682   }
2683   if (a->IsLessThan(0))
2684   {
2685     // argument is < zero, can't do
2686     unsigned long mycode(0);
2687     std::string myif("Expression Building");
2688     std::string myscope("Log10");
2689     std::string myop("value <= 0");
2690     std::string mydesc("log10(<=0) is undefined");
2691     std::string myinfo(HELPURL);
2692     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2693   }
2694   // go for it
2695   if (a->IsLeaf() && a->GetOpType() == CONST)
2696   {
2697     Expression ret;
2698     ret.SetToCopyOf(a);
2699     double t = ret->GetValue();
2700     assert(t >= 0);
2701     ret->SetCoeff(1.0);
2702     ret->SetValue(log10(t));
2703     ret->SetExponent(1.0);
2704     ret->SetOpType(CONST);
2705     return ret;
2706   }
2707   else
2708   {
2709     Expression ret;
2710     ret->SetCoeff(1.0);
2711     ret->SetExponent(1.0);
2712     ret->SetOpType(LOG10);
2713     ret->AddCopyOfNode(a);
2714     return ret;
2715   }
2716 }
2717 
Log(Expression a)2718 Expression Log(Expression a)
2719 {
2720   // make a preliminary check
2721   if (a->IsZero())
2722   {
2723     // *this is zero, can't do
2724     unsigned long mycode(0);
2725     std::string myif("Expression Building");
2726     std::string myscope("Log");
2727     std::string myop("IsZero()");
2728     std::string mydesc("log(0) is undefined");
2729     std::string myinfo(HELPURL);
2730     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2731   }
2732   if (a->IsLessThan(0))
2733   {
2734     // argument is < zero, can't do
2735     unsigned long mycode(0);
2736     std::string myif("Expression Building");
2737     std::string myscope("Log");
2738     std::string myop("value <= 0");
2739     std::string mydesc("log(<=0) is undefined");
2740     std::string myinfo(HELPURL);
2741     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2742   }
2743   // go for it
2744   if (a->IsLeaf() && a->GetOpType() == CONST)
2745   {
2746     Expression ret;
2747     ret.SetToCopyOf(a);
2748     double t = ret->GetValue();
2749     assert(t >= 0);
2750     ret->SetCoeff(1.0);
2751     ret->SetValue(log(t));
2752     ret->SetExponent(1.0);
2753     ret->SetOpType(CONST);
2754     return ret;
2755   }
2756   else
2757   {
2758     Expression ret;
2759     ret->SetCoeff(1.0);
2760     ret->SetExponent(1.0);
2761     ret->SetOpType(LOG);
2762     ret->AddCopyOfNode(a);
2763     return ret;
2764   }
2765 }
2766 
Ln(Expression a)2767 Expression Ln(Expression a)
2768 {
2769   // make a preliminary check
2770   if (a->IsZero())
2771   {
2772     // *this is zero, can't do
2773     unsigned long mycode(0);
2774     std::string myif("Expression Building");
2775     std::string myscope("Ln");
2776     std::string myop("IsZero()");
2777     std::string mydesc("ln(0) is undefined");
2778     std::string myinfo(HELPURL);
2779     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2780   }
2781   if (a->IsLessThan(0))
2782   {
2783     // argument is < zero, can't do
2784     unsigned long mycode(0);
2785     std::string myif("Expression Building");
2786     std::string myscope("Ln");
2787     std::string myop("value <= 0");
2788     std::string mydesc("ln(<=0) is undefined");
2789     std::string myinfo(HELPURL);
2790     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2791   }
2792   // go for it
2793   if (a->IsLeaf() && a->GetOpType() == CONST)
2794   {
2795     Expression ret;
2796     ret.SetToCopyOf(a);
2797     double t = ret->GetValue();
2798     assert(t >= 0);
2799     ret->SetCoeff(1.0);
2800     ret->SetValue(log(t));
2801     ret->SetExponent(1.0);
2802     ret->SetOpType(CONST);
2803     return ret;
2804   }
2805   else
2806   {
2807     Expression ret;
2808     ret->SetCoeff(1.0);
2809     ret->SetExponent(1.0);
2810     ret->SetOpType(LN);
2811     ret->AddCopyOfNode(a);
2812     return ret;
2813   }
2814 }
2815 
Lngamma(Expression a)2816 Expression Lngamma(Expression a)
2817 {
2818   // go for it
2819   if (a->IsLeaf() && a->GetOpType() == CONST)
2820   {
2821     Expression ret;
2822     ret.SetToCopyOf(a);
2823     ret->SetCoeff(1.0);
2824     ret->SetValue(lgamma(a->GetValue()));
2825     ret->SetExponent(1.0);
2826     ret->SetOpType(CONST);
2827     return ret;
2828   }
2829   else
2830   {
2831     Expression ret;
2832     ret->SetCoeff(1.0);
2833     ret->SetExponent(1.0);
2834     ret->SetOpType(LNGAMMA);
2835     ret->AddCopyOfNode(a);
2836     return ret;
2837   }
2838 }
2839 
Gamma(Expression a)2840 Expression Gamma(Expression a)
2841 {
2842   // go for it
2843   if (a->IsLeaf() && a->GetOpType() == CONST)
2844   {
2845     Expression ret;
2846     ret.SetToCopyOf(a);
2847     ret->SetCoeff(1.0);
2848     ret->SetValue(exp(lgamma(a->GetValue())));
2849     ret->SetExponent(1.0);
2850     ret->SetOpType(CONST);
2851     return ret;
2852   }
2853   else
2854   {
2855     Expression ret;
2856     ret->SetCoeff(1.0);
2857     ret->SetExponent(1.0);
2858     ret->SetOpType(GAMMA);
2859     ret->AddCopyOfNode(a);
2860     return ret;
2861   }
2862 }
2863 
Exp(Expression a)2864 Expression Exp(Expression a)
2865 {
2866   // go for it
2867   if (a->IsLeaf() && a->GetOpType() == CONST)
2868   {
2869     Expression ret;
2870     ret.SetToCopyOf(a);
2871     ret->SetCoeff(1.0);
2872     ret->SetValue(exp(a->GetValue()));
2873     ret->SetExponent(1.0);
2874     ret->SetOpType(CONST);
2875     return ret;
2876   }
2877   else
2878   {
2879     Expression ret;
2880     ret->SetCoeff(1.0);
2881     ret->SetExponent(1.0);
2882     ret->SetOpType(EXP);
2883     ret->AddCopyOfNode(a);
2884     return ret;
2885   }
2886 }
2887 
Erf(Expression a)2888 Expression Erf(Expression a)
2889 {
2890   // go for it
2891   if (a->IsLeaf() && a->GetOpType() == CONST)
2892   {
2893     Expression ret;
2894     ret.SetToCopyOf(a);
2895     ret->SetCoeff(1.0);
2896     ret->SetValue(erf(a->GetValue()));
2897     ret->SetExponent(1.0);
2898     ret->SetOpType(CONST);
2899     return ret;
2900   }
2901   else
2902   {
2903     Expression ret;
2904     ret->SetCoeff(1.0);
2905     ret->SetExponent(1.0);
2906     ret->SetOpType(ERF);
2907     ret->AddCopyOfNode(a);
2908     return ret;
2909   }
2910 }
2911 
Erfc(Expression a)2912 Expression Erfc(Expression a)
2913 {
2914   // go for it
2915   if (a->IsLeaf() && a->GetOpType() == CONST)
2916   {
2917     Expression ret;
2918     ret.SetToCopyOf(a);
2919     ret->SetCoeff(1.0);
2920     ret->SetValue(erfc(a->GetValue()));
2921     ret->SetExponent(1.0);
2922     ret->SetOpType(CONST);
2923     return ret;
2924   }
2925   else
2926   {
2927     Expression ret;
2928     ret->SetCoeff(1.0);
2929     ret->SetExponent(1.0);
2930     ret->SetOpType(ERFC);
2931     ret->AddCopyOfNode(a);
2932     return ret;
2933   }
2934 }
2935 
Sqrt(Expression a)2936 Expression Sqrt(Expression a)
2937 {
2938   // make a preliminary check
2939   if (a->IsLessThan(0) && !a->HasValue(0))
2940   {
2941     // argument is < zero, can't do
2942     unsigned long mycode(0);
2943     std::string myif("Expression Building");
2944     std::string myscope("Sqrt");
2945     std::string myop("value < 0");
2946     std::string mydesc("sqrt(<0) is complex, can't do");
2947     std::string myinfo(HELPURL);
2948     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
2949   }
2950   // go for it
2951   if (a->IsLeaf() && a->GetOpType() == CONST)
2952   {
2953     Expression ret;
2954     ret.SetToCopyOf(a);
2955     double t = a->GetValue();
2956     assert(t >= 0);
2957     ret->SetCoeff(1.0);
2958     ret->SetValue(sqrt(t));
2959     ret->SetExponent(1.0);
2960     ret->SetOpType(CONST);
2961     return ret;
2962   }
2963   else
2964   {
2965     Expression ret;
2966     ret->SetCoeff(1.0);
2967     ret->SetExponent(1.0);
2968     ret->SetOpType(SQRT);
2969     ret->AddCopyOfNode(a);
2970     return ret;
2971   }
2972 }
2973 
Cbrt(Expression a)2974 Expression Cbrt(Expression a)
2975 {
2976   // go for it
2977   if (a->IsLeaf() && a->GetOpType() == CONST)
2978   {
2979     Expression ret;
2980     ret.SetToCopyOf(a);
2981     ret->SetCoeff(1.0);
2982     ret->SetValue(cbrt(a->GetValue()));
2983     ret->SetExponent(1.0);
2984     ret->SetOpType(CONST);
2985     return ret;
2986   }
2987   else
2988   {
2989     Expression ret;
2990     ret->SetCoeff(1.0);
2991     ret->SetExponent(1.0);
2992     ret->SetOpType(CBRT);
2993     ret->AddCopyOfNode(a);
2994     return ret;
2995   }
2996 }
2997 
BesselJ0(Expression a)2998 Expression BesselJ0(Expression a)
2999 {
3000   // go for it
3001   if (a->IsLeaf() && a->GetOpType() == CONST)
3002   {
3003     Expression ret;
3004     ret.SetToCopyOf(a);
3005     ret->SetCoeff(1.0);
3006     ret->SetValue(j0(a->GetValue()));
3007     ret->SetExponent(1.0);
3008     ret->SetOpType(CONST);
3009     return ret;
3010   }
3011   else
3012   {
3013     Expression ret;
3014     ret->SetCoeff(1.0);
3015     ret->SetExponent(1.0);
3016     ret->SetOpType(BESSELJ0);
3017     ret->AddCopyOfNode(a);
3018     return ret;
3019   }
3020 }
3021 
BesselJ1(Expression a)3022 Expression BesselJ1(Expression a)
3023 {
3024   // go for it
3025   if (a->IsLeaf() && a->GetOpType() == CONST)
3026   {
3027     Expression ret;
3028     ret.SetToCopyOf(a);
3029     ret->SetCoeff(1.0);
3030     ret->SetValue(j1(a->GetValue()));
3031     ret->SetExponent(1.0);
3032     ret->SetOpType(CONST);
3033     return ret;
3034   }
3035   else
3036   {
3037     Expression ret;
3038     ret->SetCoeff(1.0);
3039     ret->SetExponent(1.0);
3040     ret->SetOpType(BESSELJ1);
3041     ret->AddCopyOfNode(a);
3042     return ret;
3043   }
3044 }
3045 
BesselY0(Expression a)3046 Expression BesselY0(Expression a)
3047 {
3048   // go for it
3049   if (a->IsLeaf() && a->GetOpType() == CONST)
3050   {
3051     Expression ret;
3052     ret.SetToCopyOf(a);
3053     ret->SetCoeff(1.0);
3054     ret->SetValue(y0(a->GetValue()));
3055     ret->SetExponent(1.0);
3056     ret->SetOpType(CONST);
3057     return ret;
3058   }
3059   else
3060   {
3061     Expression ret;
3062     ret->SetCoeff(1.0);
3063     ret->SetExponent(1.0);
3064     ret->SetOpType(BESSELY0);
3065     ret->AddCopyOfNode(a);
3066     return ret;
3067   }
3068 }
3069 
BesselY1(Expression a)3070 Expression BesselY1(Expression a)
3071 {
3072   // go for it
3073   if (a->IsLeaf() && a->GetOpType() == CONST)
3074   {
3075     Expression ret;
3076     ret.SetToCopyOf(a);
3077     ret->SetCoeff(1.0);
3078     ret->SetValue(y1(a->GetValue()));
3079     ret->SetExponent(1.0);
3080     ret->SetOpType(CONST);
3081     return ret;
3082   }
3083   else
3084   {
3085     Expression ret;
3086     ret->SetCoeff(1.0);
3087     ret->SetExponent(1.0);
3088     ret->SetOpType(BESSELY1);
3089     ret->AddCopyOfNode(a);
3090     return ret;
3091   }
3092 }
3093 
Sign(Expression a)3094 Expression Sign(Expression a)
3095 {
3096   // go for it
3097   if (a->IsLeaf() && a->GetOpType() == CONST)
3098   {
3099     Expression ret;
3100     ret.SetToCopyOf(a);
3101     ret->SetCoeff(1.0);
3102     double val = a->GetValue();
3103     ret->SetValue((val < 0.0) ? -1.0 : (val > 0.0) ? 1.0 : 0.0);
3104     ret->SetExponent(1.0);
3105     ret->SetOpType(CONST);
3106     return ret;
3107   }
3108   else
3109   {
3110     Expression ret;
3111     ret->SetCoeff(1.0);
3112     ret->SetExponent(1.0);
3113     ret->SetOpType(SIGN);
3114     ret->AddCopyOfNode(a);
3115     return ret;
3116   }
3117 }
3118 
Rint(Expression a)3119 Expression Rint(Expression a)
3120 {
3121   // go for it
3122   if (a->IsLeaf() && a->GetOpType() == CONST)
3123   {
3124     Expression ret;
3125     ret.SetToCopyOf(a);
3126     ret->SetCoeff(1.0);
3127     ret->SetValue(floor(0.5 + a->GetValue()));
3128     ret->SetExponent(1.0);
3129     ret->SetOpType(CONST);
3130     return ret;
3131   }
3132   else
3133   {
3134     Expression ret;
3135     ret->SetCoeff(1.0);
3136     ret->SetExponent(1.0);
3137     ret->SetOpType(RINT);
3138     ret->AddCopyOfNode(a);
3139     return ret;
3140   }
3141 }
3142 
Abs(Expression a)3143 Expression Abs(Expression a)
3144 {
3145   // go for it
3146   if (a->IsLeaf() && a->GetOpType() == CONST)
3147   {
3148     Expression ret;
3149     ret.SetToCopyOf(a);
3150     ret->SetCoeff(1.0);
3151     ret->SetValue(std::abs(a->GetValue()));
3152     ret->SetExponent(1.0);
3153     ret->SetOpType(CONST);
3154     return ret;
3155   }
3156   else
3157   {
3158     Expression ret;
3159     ret->SetCoeff(1.0);
3160     ret->SetExponent(1.0);
3161     ret->SetOpType(ABS);
3162     ret->AddCopyOfNode(a);
3163     return ret;
3164   }
3165 }
3166 
Cot(Expression a)3167 Expression Cot(Expression a)
3168 {
3169   // make a preliminary check
3170   if (a->IsZero())
3171   {
3172     // *this is zero, can't do
3173     unsigned long mycode(0);
3174     std::string myif("Expression Building");
3175     std::string myscope("Cot");
3176     std::string myop("IsZero()");
3177     std::string mydesc("cot(0) is undefined");
3178     std::string myinfo(HELPURL);
3179     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
3180   }
3181   // go for it
3182   if (a->IsLeaf() && a->GetOpType() == CONST)
3183   {
3184     Expression ret;
3185     ret.SetToCopyOf(a);
3186     double t = tan(a->GetValue());
3187     assert(t != 0);
3188     ret->SetCoeff(1.0);
3189     ret->SetValue(1 / t);
3190     ret->SetExponent(1.0);
3191     ret->SetOpType(CONST);
3192     return ret;
3193   }
3194   else
3195   {
3196     Expression ret;
3197     ret->SetCoeff(1.0);
3198     ret->SetExponent(1.0);
3199     ret->SetOpType(COT);
3200     ret->AddCopyOfNode(a);
3201     return ret;
3202   }
3203 }
3204 
Coth(Expression a)3205 Expression Coth(Expression a)
3206 {
3207   // make a preliminary check
3208   if (a->IsZero())
3209   {
3210     // *this is zero, can't do
3211     unsigned long mycode(0);
3212     std::string myif("Expression Building");
3213     std::string myscope("Coth");
3214     std::string myop("IsZero()");
3215     std::string mydesc("coth(0) is undefined");
3216     std::string myinfo(HELPURL);
3217     throw ErrNotPermitted(mycode, myif, myscope, myop, mydesc, myinfo);
3218   }
3219   // go for it
3220   if (a->IsLeaf() && a->GetOpType() == CONST)
3221   {
3222     Expression ret;
3223     ret.SetToCopyOf(a);
3224     double t = tanh(a->GetValue());
3225     assert(t != 0);
3226     ret->SetCoeff(1.0);
3227     ret->SetValue(1 / t);
3228     ret->SetExponent(1.0);
3229     ret->SetOpType(CONST);
3230     return ret;
3231   }
3232   else
3233   {
3234     Expression ret;
3235     ret->SetCoeff(1.0);
3236     ret->SetExponent(1.0);
3237     ret->SetOpType(COTH);
3238     ret->AddCopyOfNode(a);
3239     return ret;
3240   }
3241 }
3242 
3243 /***************** expression creation (affects arguments) ***********/
3244 
3245 // sums:
SumLink(Expression a,Expression b)3246 Expression SumLink(Expression a,
3247                    Expression b)
3248 {
3249   // make a preliminary check
3250   if (a->GetCoeff() == 0 || a->HasValue(0))
3251     return b;
3252   if (b->GetCoeff() == 0 || b->HasValue(0))
3253     return a;
3254   if (!(a->IsConstant() && b->IsConstant()) && a->IsEqualToNoCoeff(b))
3255   {
3256     a->SetCoeff(a->GetCoeff() + b->GetCoeff());
3257     if (std::abs(a->GetCoeff()) < Ev3NearZero())
3258     {
3259       // simplify to zero - for differences
3260       Expression zero(0.0);
3261       return zero;
3262     }
3263     else
3264       return a;
3265   }
3266   // go for it
3267   if (a->IsLeaf() && a->GetOpType() == CONST &&
3268       b->IsLeaf() && b->GetOpType() == CONST)
3269   {
3270     // a, b are numbers - add them
3271     a->SetValue(a->GetValue() + b->GetValue());
3272     a->SetCoeff(1.0);
3273     a->SetExponent(1.0);
3274     return a;
3275   }
3276   else if (a->IsLeaf() && a->GetOpType() == VAR &&
3277            b->IsLeaf() && b->GetOpType() == VAR &&
3278            a->GetVarIndex() == b->GetVarIndex() &&
3279            a->GetExponent() == b->GetExponent())
3280   {
3281     // a, b are the same variable - add coefficients
3282     a->SetCoeff(a->GetCoeff() + b->GetCoeff());
3283     return a;
3284   }
3285   else if (a->GetOpType() == SUM && b->GetOpType() != SUM)
3286   {
3287     // a is a sum and b isn't - just add the term b
3288     a->DistributeCoeffOverSum();
3289     Int i = 0;
3290     bool couldsimplify = false;
3291     Expression tmp;
3292     // if t is a leaf and there is a like leaf in this,
3293     // just add it to the value/coefficient
3294     if (b->IsLeaf() && b->GetOpType() == CONST)
3295     {
3296       // b is a constant
3297       for (i = 0; i < a->GetSize(); i++)
3298       {
3299         tmp = a->GetNode(i);
3300         if (tmp->IsLeaf() && tmp->GetOpType() == CONST)
3301         {
3302           tmp->SetValue(tmp->GetValue() + b->GetValue() / a->GetCoeff());
3303           tmp->SetCoeff(1.0);
3304           tmp->SetExponent(1.0); // NB: changing tmp should also change a
3305           couldsimplify = true;
3306           break;
3307         }
3308       }
3309     }
3310     else if (b->IsLeaf() && b->GetOpType() == VAR)
3311     {
3312       // b is a variable
3313       for (i = 0; i < a->GetSize(); i++)
3314       {
3315         if (a->GetNode(i)->IsLeaf() && a->GetNode(i)->GetOpType() == VAR &&
3316             b->GetVarIndex() == a->GetNode(i)->GetVarIndex() &&
3317             b->GetExponent() == a->GetNode(i)->GetExponent())
3318         {
3319           double tc = a->GetNode(i)->GetCoeff() + b->GetCoeff() / a->GetCoeff();
3320           // warning: tc could be zero, but it would be cumbersome
3321           // to simplify it here - do it in SimplifyConstant
3322           a->GetNode(i)->SetCoeff(tc);
3323           couldsimplify = true;
3324           break;
3325         }
3326       }
3327     }
3328     else if (!b->IsLeaf())
3329     {
3330       // a is a sum, b is a nonleaf, look for a subnode of a similar to b
3331       for (i = 0; i < a->GetSize(); i++)
3332       {
3333         if (a->GetNode(i)->IsEqualTo(b))
3334         {
3335           // found one, add coefficients - notice, as above, coeff could
3336           // be zero, but deal with that case in SimplifyConstant
3337           a->GetNode(i)->SetCoeff(a->GetNode(i)->GetCoeff() + b->GetCoeff());
3338           couldsimplify = true;
3339           break;
3340         }
3341       }
3342     }
3343     if (!couldsimplify)
3344     {
3345       // either could not simplify in steps above, or b is an operator
3346       a->AddNode(b);
3347     }
3348     return a;
3349   }
3350   else if (a->GetOpType() == SUM && b->GetOpType() == SUM)
3351   {
3352     // a, b are sums - add terms of b to a
3353     b->DistributeCoeffOverSum();
3354     Int i = 0;
3355     Int s = b->GetSize();
3356     for (i = 0; i < s; i++)
3357     {
3358       a = SumLink(a, b->GetNode(i));
3359     }
3360     return a;
3361   }
3362   else if (a->GetOpType() != SUM && b->GetOpType() == SUM)
3363   {
3364     // a is not a sum but b is - transform this into a sum
3365     b = SumLink(b, a);
3366     return b;
3367   }
3368   else
3369   {
3370     // all other cases - make new node on top of the addends
3371     Expression ret;
3372 
3373 
3374     ret->SetOpType(SUM);
3375     ret->SetCoeff(1.0);
3376     ret->SetExponent(1.0);
3377     ret->AddNode(a);
3378     ret->AddNode(b);
3379 
3380     return ret;
3381   }
3382 }
3383 
3384 
3385 // product
ProductLink(Expression a,Expression t)3386 Expression ProductLink(Expression a,
3387                        Expression t)
3388 {
3389   // make a preliminary check
3390   if (a->GetCoeff() == 0 || t->GetCoeff() == 0 ||
3391       a->HasValue(0) || t->HasValue(0))
3392   {
3393     Expression zero(0.0);
3394     return zero;
3395   }
3396   if (a->HasValue(1))
3397     return t;
3398   if (t->HasValue(1))
3399     return a;
3400   if (!(a->IsConstant() && t->IsConstant()) && a->IsEqualToNoCoeff(t))
3401   {
3402     Expression two(2.0);
3403     double c = a->GetCoeff();
3404     a->SetCoeff(1.);
3405     Expression power2(a ^ two);
3406     power2->SetCoeff(c * t->GetCoeff());
3407     return power2;
3408   }
3409   // go for it
3410   if (a->IsLeaf() && a->GetOpType() == CONST &&
3411       t->IsLeaf() && t->GetOpType() == CONST)
3412   {
3413     // a, t are numbers - multiply them
3414     a->SetValue(a->GetValue() * t->GetValue());
3415     a->SetCoeff(1.0);
3416     a->SetExponent(1.0);
3417     return a;
3418   }
3419   else if (a->IsLeaf() && a->GetOpType() == VAR &&
3420            t->IsLeaf() && t->GetOpType() == VAR &&
3421            a->GetVarIndex() == t->GetVarIndex())
3422   {
3423     // a, t are the same variable - multiply coefficients
3424     // and add exponents
3425     a->SetCoeff(a->GetCoeff() * t->GetCoeff());
3426     a->SetExponent(a->GetExponent() + t->GetExponent());
3427     return a;
3428   }
3429   else if (t->IsConstant())
3430   {
3431     // t is constant, set coeff of a
3432     a->SetCoeff(a->GetCoeff() * t->GetValue());
3433     a->DistributeCoeffOverSum();
3434     return a;
3435   }
3436   else if (a->IsConstant())
3437   {
3438     // a is constant, set coeff of t
3439     t->SetCoeff(t->GetCoeff() * a->GetValue());
3440     t->DistributeCoeffOverSum();
3441     return t;
3442   }
3443   else if (a->GetOpType() == PRODUCT && t->GetOpType() != PRODUCT)
3444   {
3445     // a is a product and t isn't - just multiply the term t
3446     Int i = 0;
3447     bool couldsimplify = false;
3448     if (t->IsLeaf() && t->GetOpType() == VAR)
3449     {
3450       // t is a variable
3451       Expression tmp;
3452       for (i = 0; i < a->GetSize(); i++)
3453       {
3454         tmp = a->GetNode(i);
3455         if (tmp->IsLeaf() && tmp->GetOpType() == VAR &&
3456             t->GetVarIndex() == tmp->GetVarIndex())
3457         {
3458           // found same variable in a, multiply coeffs and add exponents
3459           tmp->SetCoeff(tmp->GetCoeff() * t->GetCoeff());
3460           tmp->SetExponent(tmp->GetExponent() + t->GetExponent());
3461           couldsimplify = true;
3462           break;
3463         }
3464       }
3465     }
3466     // here we shan't try to simplify f*f <-- f^2 (f nonleaf)
3467     // because a product of nonleaves is easier to manipulate than
3468     // a power (as it adds a depth level)
3469     if (!couldsimplify)
3470     {
3471       // either could not simplify in steps above, or t is an operator
3472       a->AddNode(t);
3473     }
3474     return a;
3475   }
3476   else if (a->GetOpType() == PRODUCT && t->GetOpType() == PRODUCT)
3477   {
3478     // a, t are products - multiply terms of t to a
3479     t->DistributeCoeffOverProduct();
3480     Int i = 0;
3481     Int s = t->GetSize();
3482     for (i = 0; i < s; i++)
3483     {
3484       a = ProductLink(a, t->GetNode(i));
3485     }
3486     return a;
3487   }
3488   else if (a->GetOpType() != PRODUCT && t->GetOpType() == PRODUCT)
3489   {
3490     // a is not a products but t is - transform this into a product
3491     t = ProductLink(t, a);
3492     return t;
3493   }
3494   else
3495   {
3496     // all other cases - make new node on top of the addends
3497     Expression ret;
3498     ret->SetCoeff(1.0);
3499     ret->SetExponent(1.0);
3500     ret->SetOpType(PRODUCT);
3501     ret->AddNode(a);
3502     ret->AddNode(t);
3503     return ret;
3504   }
3505 }
3506 
3507 // fractions:
FractionLink(Expression a,Expression t)3508 Expression FractionLink(Expression a,
3509                         Expression t)
3510 {
3511   // make a preliminary check
3512   if (t->GetCoeff() == 0)
3513   {
3514     // divide by zero
3515     unsigned long mycode(0);
3516     std::string myif("Expression Building");
3517     std::string myscope("FractionLink");
3518     std::string myop("t.GetCoeff()==0");
3519     std::string mydesc("Divisor cannot be zero");
3520     std::string myinfo(HELPURL);
3521     std::string mydiv(NONE);
3522     throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
3523   }
3524   if (a->GetCoeff() == 0 || a->HasValue(0))
3525   {
3526     // dividend has zero coeff, return zero
3527     Expression zero(0.0);
3528     return zero;
3529   }
3530   if (t->HasValue(1))
3531     return a;
3532   if (!(a->IsConstant() && t->IsConstant()) && a->IsEqualToNoCoeff(t))
3533   {
3534     // dividend = divisor, return ratio of coefficients
3535     Expression one(1.0);
3536     one->SetCoeff(a->GetCoeff() / t->GetCoeff());
3537     return one;
3538   }
3539   // go for it
3540   if (a->IsLeaf() && a->GetOpType() == CONST &&
3541       t->IsLeaf() && t->GetOpType() == CONST)
3542   {
3543     // a, t are numbers - divide them
3544     if (t->GetValue() == 0)
3545     {
3546       unsigned long mycode(0);
3547       std::string myif("Expression Building");
3548       std::string myscope("FractionLink");
3549       std::string myop("t.GetValue()==0");
3550       std::string mydesc("Divisor cannot be zero");
3551       std::string myinfo(HELPURL);
3552       std::string mydiv(NONE);
3553       throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
3554     }
3555     else
3556     {
3557       a->SetValue(a->GetValue() / t->GetValue());
3558       a->SetCoeff(1.0);
3559       a->SetExponent(1.0);
3560       return a;
3561     }
3562   }
3563   else if (t->HasValue(1))
3564   {
3565     // divide by constant 1, don't do anything
3566     return a;
3567   }
3568   else if (t->IsConstant())
3569   {
3570     // t is constant, set coeff of a
3571     a->SetCoeff(a->GetCoeff() / t->GetValue());
3572     a->DistributeCoeffOverSum();
3573     return a;
3574   }
3575   else if (a->IsVariable() && t->IsVariable() &&
3576            a->GetVarIndex() == t->GetVarIndex())
3577   {
3578     // cx^e / dx^f = (c/d)x^(e-f)
3579     double te = a->GetExponent() - t->GetExponent();
3580     double tc = a->GetCoeff() / t->GetCoeff();
3581     if (std::abs(te) < Ev3NearZero())
3582     {
3583       Expression c(tc);
3584       return c;
3585     }
3586     a->SetCoeff(tc);
3587     a->SetExponent(te);
3588     return a;
3589   }
3590   else if (a->IsVariable() && t->GetOpType() == PRODUCT)
3591   {
3592     // a is a variable, t is a product - see if a appears in t
3593     // and cancel common term
3594     // first simplify coeffs of divisor
3595     t->ConsolidateProductCoeffs();
3596     // denominator
3597     if (std::abs(t->GetCoeff()) < Ev3NearZero())
3598     {
3599       // divide by zero
3600       unsigned long mycode(22);
3601       std::string myif("Expression Building");
3602       std::string myscope("FractionLink");
3603       std::string myop("t->GetCoeff()");
3604       std::string mydesc("Divisor cannot be zero");
3605       std::string myinfo(HELPURL);
3606       std::string mydiv(NONE);
3607       throw ErrDivideByZero(mycode, myif, myscope, myop, mydesc, myinfo, mydiv);
3608     }
3609     if (std::abs(a->GetCoeff()) < Ev3NearZero())
3610     {
3611       Expression zero(0.0);
3612       return zero;
3613     }
3614     double accumulatedcoeff = a->GetCoeff() / t->GetCoeff();
3615     a->SetCoeff(1.0);
3616     t->SetCoeff(1.0);
3617     // now try simplification
3618     Int i;
3619     for (i = 0; i < t->GetSize(); i++)
3620     {
3621       if (t->GetNode(i)->GetOpType() == VAR &&
3622           a->GetVarIndex() == t->GetNode(i)->GetVarIndex())
3623       {
3624         double te = a->GetExponent() - t->GetNode(i)->GetExponent();
3625         if (std::abs(te) < Ev3NearZero())
3626         {
3627           // exponents are the same, just cancel
3628           a->One();
3629           t->DeleteNode(i);
3630         }
3631         else if (te > 0)
3632         {
3633           // numerator remains, cancel denominator
3634           a->SetExponent(te);
3635           t->DeleteNode(i);
3636         }
3637         else if (te < 0)
3638         {
3639           // numerator goes to one, denominator remains
3640           a->One();
3641           t->GetNode(i)->SetExponent(-te);
3642         }
3643         // exit loop
3644         break;
3645       }
3646     }
3647     // check that denominator (t) has more than one operands;
3648     // if not, bring up a rank level
3649     if (t->GetSize() == 1)
3650     {
3651       t = t->GetNode(0);
3652     }
3653     // build ratio
3654     Expression ret;
3655     ret->SetOpType(FRACTION);
3656     ret->SetCoeff(accumulatedcoeff);
3657     ret->SetExponent(1.0);
3658     ret->AddNode(a);
3659     ret->AddNode(t);
3660     return ret;
3661   }
3662   else if (t->IsVariable() && a->GetOpType() == PRODUCT)
3663   {
3664     // t is a variable, a is a product - see if t appears in a
3665     // and cancel common term
3666     // first simplify coeffs of divisor
3667     a->ConsolidateProductCoeffs();
3668     // denominator - already checked
3669     if (std::abs(a->GetCoeff()) < Ev3NearZero())
3670     {
3671       Expression zero(0.0);
3672       return zero;
3673     }
3674     double accumulatedcoeff = a->GetCoeff() / t->GetCoeff();
3675     a->SetCoeff(1.0);
3676     t->SetCoeff(1.0);
3677     // now try simplification
3678     Int i;
3679     for (i = 0; i < a->GetSize(); i++)
3680     {
3681       if (a->GetNode(i)->GetOpType() == VAR &&
3682           t->GetVarIndex() == a->GetNode(i)->GetVarIndex())
3683       {
3684         double te = a->GetNode(i)->GetExponent() - t->GetExponent();
3685         if (std::abs(te) < Ev3NearZero())
3686         {
3687           // exponents are the same, just cancel
3688           t->One();
3689           a->DeleteNode(i);
3690         }
3691         else if (te > 0)
3692         {
3693           // numerator remains, cancel denominator
3694           t->One();
3695           a->GetNode(i)->SetExponent(te);
3696         }
3697         else if (te < 0)
3698         {
3699           // numerator goes to one, denominator remains
3700           t->SetExponent(-te);
3701           a->DeleteNode(i);
3702         }
3703         // exit loop
3704         break;
3705       }
3706     }
3707     // check that numerator (a) has more than one operands;
3708     // if not, bring up a rank level
3709     if (a->GetSize() == 1)
3710     {
3711       a = a->GetNode(0);
3712     }
3713     // build ratio
3714     Expression ret;
3715     ret->SetOpType(FRACTION);
3716     ret->SetCoeff(accumulatedcoeff);
3717     ret->SetExponent(1.0);
3718     ret->AddNode(a);
3719     ret->AddNode(t);
3720     return ret;
3721   }
3722   else if (a->GetOpType() == PRODUCT && t->GetOpType() == PRODUCT)
3723   {
3724     // a, t are products, try to cancel common terms
3725     Int i = 0, j = 0;
3726     double accumulatedcoeff;
3727     // first simplify coefficients of operands
3728     a->ConsolidateProductCoeffs();
3729     t->ConsolidateProductCoeffs();
3730     // denominator
3731     if (std::abs(t->GetCoeff()) < Ev3NearZero())
3732       throw ErrDivideByZero(21, "Expression Building", "FractionLink", "t->GetCoeff()", "Divisor cannot be zero", HELPURL, NONE);
3733 
3734     if (std::abs(a->GetCoeff()) < Ev3NearZero())
3735     {
3736       Expression zero(0.0);
3737       return zero;
3738     }
3739     // save ratio of coeffs of products
3740     accumulatedcoeff = a->GetCoeff() / t->GetCoeff();
3741     a->SetCoeff(1.0);
3742     t->SetCoeff(1.0);
3743     // now try simplification
3744     i = 0;
3745     bool isnumeratorempty = false;
3746     bool isdenominatorempty = false;
3747     int szi = a->GetSize();
3748     int szj = t->GetSize();
3749     while(!isnumeratorempty && !isdenominatorempty && i < szi)
3750     {
3751       j = 0;
3752       while(!isnumeratorempty && !isdenominatorempty && j < szj)
3753       {
3754         if (a->GetNode(i)->IsEqualTo(t->GetNode(j)))
3755         {
3756           // found like terms i and j
3757           a->DeleteNode(i);
3758           szi--;
3759           if(szi == 0)
3760           {
3761             isnumeratorempty = true;
3762             a->One();
3763           }
3764           t->DeleteNode(j);
3765           szj--;
3766           if (szj == 0)
3767           {
3768             isdenominatorempty = true;
3769             t->One();
3770           }
3771           i--;   // cancel the effect of the later i++
3772           break; // go to outer cycle
3773         }
3774         else
3775         {
3776           j++;
3777         }
3778       }
3779       i++;
3780     }
3781     if (t->HasValue(1))
3782     {
3783       // denominator is 1, return a
3784       a->SetCoeff(accumulatedcoeff);
3785       return a;
3786     }
3787     // now construct fraction
3788     // check that numerator, denominator have more than one operands;
3789     // if not, bring up a rank level
3790     if (a->GetSize() == 1)
3791     {
3792       a = a->GetNode(0);
3793     }
3794     if (t->GetSize() == 1)
3795     {
3796       t = t->GetNode(0);
3797     }
3798     Expression ret;
3799     ret->SetCoeff(accumulatedcoeff); // already contains coeffs of a, t
3800     ret->SetExponent(1.0);
3801     ret->SetOpType(FRACTION);
3802     ret->AddNode(a);
3803     ret->AddNode(t);
3804     return ret;
3805   }
3806   else
3807   {
3808     Expression ret;
3809     ret->SetCoeff(a->GetCoeff() / t->GetCoeff());
3810     a->SetCoeff(1.0);
3811     t->SetCoeff(1.0);
3812     ret->SetExponent(1.0);
3813     ret->SetOpType(FRACTION);
3814     ret->AddNode(a);
3815     ret->AddNode(t);
3816     return ret;
3817   }
3818 }
3819 
3820 // unary minus:
MinusLink(Expression a)3821 Expression MinusLink(Expression a)
3822 {
3823   if (a->IsLeaf() && a->GetOpType() == CONST)
3824   {
3825     a->SetValue(- a->GetValue());
3826     a->SetCoeff(1.0);
3827     a->SetExponent(1.0);
3828   }
3829   else
3830   {
3831     a->SetCoeff(- a->GetCoeff());
3832   }
3833   return a;
3834 }
3835 
3836 // binary minus:
DifferenceLink(Expression a,Expression b)3837 Expression DifferenceLink(Expression a,
3838                           Expression b)
3839 {
3840   if (a->HasValue(0))
3841     return MinusLink(b);
3842   if (b->HasValue(0))
3843     return a;
3844   return SumLink(a, MinusLink(b));
3845 }
3846 
3847 // power:
PowerLink(Expression a,Expression t)3848 Expression PowerLink(Expression a,
3849                      Expression t)
3850 {
3851   // make a preliminary check
3852   if (a->GetCoeff() == 0)
3853   {
3854     // *this is zero, just return zero
3855     Expression zero(0.0);
3856     return zero;
3857   }
3858   if (t->HasValue(0.0))
3859   {
3860     // exponent is 0, just return 1
3861     Expression one(1.0);
3862     return one;
3863   }
3864   else if (t->HasValue(1.0))
3865   {
3866     // exponent is 1, just return a
3867     return a;
3868   }
3869   if (a->HasValue(0.0))
3870   {
3871     // base is zero, return 0
3872     Expression zero(0.0);
3873     return zero;
3874   }
3875   else if (a->HasValue(1.0))
3876   {
3877     // base is one, return 1
3878     Expression one(1.0);
3879     return one;
3880   }
3881   // go for it
3882   if (a->IsLeaf() && a->GetOpType() == CONST &&
3883       t->IsLeaf() && t->GetOpType() == CONST)
3884   {
3885     // constant to constant
3886     a->SetValue(pow(a->GetValue(), t->GetValue()));
3887     a->SetCoeff(1.0);
3888     a->SetExponent(1.0);
3889     return a;
3890   }
3891   else if ((std::abs(a->GetCoeff()) == 1.0) && a->IsLeaf() && (a->GetOpType() == VAR) &&
3892            t->IsLeaf() && (t->GetOpType() == CONST))
3893   {
3894     // variable to constant
3895     a->SetExponent(a->GetExponent() * t->GetValue());
3896     return a;
3897   }
3898   else
3899   {
3900     Expression ret;
3901     ret->SetCoeff(1.0);
3902     ret->SetExponent(1.0);
3903     ret->SetOpType(POWER);
3904     ret->AddNode(a);
3905     ret->AddNode(t);
3906     return ret;
3907   }
3908 }
3909 
SinLink(Expression a)3910 Expression SinLink(Expression a)
3911 {
3912   // go for it
3913   if (a->IsLeaf() && a->GetOpType() == CONST)
3914   {
3915     a->SetValue(sin(a->GetValue()));
3916     a->SetCoeff(1.0);
3917     a->SetExponent(1.0);
3918     a->SetOpType(CONST);
3919     return a;
3920   }
3921   else
3922   {
3923     Expression ret;
3924     ret->SetCoeff(1.0);
3925     ret->SetExponent(1.0);
3926     ret->SetOpType(SIN);
3927     ret->AddNode(a);
3928     return ret;
3929   }
3930 }
3931 
CosLink(Expression a)3932 Expression CosLink(Expression a)
3933 {
3934   // go for it
3935   if (a->IsLeaf() && a->GetOpType() == CONST)
3936   {
3937     a->SetValue(cos(a->GetValue()));
3938     a->SetCoeff(1.0);
3939     a->SetExponent(1.0);
3940     a->SetOpType(CONST);
3941     return a;
3942   }
3943   else
3944   {
3945     Expression ret;
3946     ret->SetCoeff(1.0);
3947     ret->SetExponent(1.0);
3948     ret->SetOpType(COS);
3949     ret->AddNode(a);
3950     return ret;
3951   }
3952 }
3953 
TanLink(Expression a)3954 Expression TanLink(Expression a)
3955 {
3956   // go for it
3957   if (a->IsLeaf() && a->GetOpType() == CONST)
3958   {
3959     a->SetValue(tan(a->GetValue()));
3960     a->SetCoeff(1.0);
3961     a->SetExponent(1.0);
3962     a->SetOpType(CONST);
3963     return a;
3964   }
3965   else
3966   {
3967     Expression ret;
3968     ret->SetCoeff(1.0);
3969     ret->SetExponent(1.0);
3970     ret->SetOpType(TAN);
3971     ret->AddNode(a);
3972     return ret;
3973   }
3974 }
3975 
AsinLink(Expression a)3976 Expression AsinLink(Expression a)
3977 {
3978   // go for it
3979   if (a->IsLeaf() && a->GetOpType() == CONST)
3980   {
3981     a->SetValue(asin(a->GetValue()));
3982     a->SetCoeff(1.0);
3983     a->SetExponent(1.0);
3984     a->SetOpType(CONST);
3985     return a;
3986   }
3987   else
3988   {
3989     Expression ret;
3990     ret->SetCoeff(1.0);
3991     ret->SetExponent(1.0);
3992     ret->SetOpType(ASIN);
3993     ret->AddNode(a);
3994     return ret;
3995   }
3996 }
3997 
AcosLink(Expression a)3998 Expression AcosLink(Expression a)
3999 {
4000   if (a->IsLessThan(-1.0) || a->IsGreaterThan(1.0))
4001     throw ErrNotPermitted(0, "Expression Building", "AcosLink", "value <-1|>1", "acos(<-1|>1) is undefined", HELPURL);
4002 
4003   // go for it
4004   if (a->IsLeaf() && a->GetOpType() == CONST)
4005   {
4006     a->SetValue(acos(a->GetValue()));
4007     a->SetCoeff(1.0);
4008     a->SetExponent(1.0);
4009     a->SetOpType(CONST);
4010     return a;
4011   }
4012   else
4013   {
4014     Expression ret;
4015     ret->SetCoeff(1.0);
4016     ret->SetExponent(1.0);
4017     ret->SetOpType(ACOS);
4018     ret->AddNode(a);
4019     return ret;
4020   }
4021 }
4022 
AtanLink(Expression a)4023 Expression AtanLink(Expression a)
4024 {
4025   // go for it
4026   if (a->IsLeaf() && a->GetOpType() == CONST)
4027   {
4028     a->SetValue(atan(a->GetValue()));
4029     a->SetCoeff(1.0);
4030     a->SetExponent(1.0);
4031     a->SetOpType(CONST);
4032     return a;
4033   }
4034   else
4035   {
4036     Expression ret;
4037     ret->SetCoeff(1.0);
4038     ret->SetExponent(1.0);
4039     ret->SetOpType(ATAN);
4040     ret->AddNode(a);
4041     return ret;
4042   }
4043 }
4044 
SinhLink(Expression a)4045 Expression SinhLink(Expression a)
4046 {
4047   // go for it
4048   if (a->IsLeaf() && a->GetOpType() == CONST)
4049   {
4050     a->SetValue(sinh(a->GetValue()));
4051     a->SetCoeff(1.0);
4052     a->SetExponent(1.0);
4053     a->SetOpType(CONST);
4054     return a;
4055   }
4056   else
4057   {
4058     Expression ret;
4059     ret->SetCoeff(1.0);
4060     ret->SetExponent(1.0);
4061     ret->SetOpType(SINH);
4062     ret->AddNode(a);
4063     return ret;
4064   }
4065 }
4066 
CoshLink(Expression a)4067 Expression CoshLink(Expression a)
4068 {
4069   // go for it
4070   if (a->IsLeaf() && a->GetOpType() == CONST)
4071   {
4072     a->SetValue(cosh(a->GetValue()));
4073     a->SetCoeff(1.0);
4074     a->SetExponent(1.0);
4075     a->SetOpType(CONST);
4076     return a;
4077   }
4078   else
4079   {
4080     Expression ret;
4081     ret->SetCoeff(1.0);
4082     ret->SetExponent(1.0);
4083     ret->SetOpType(COSH);
4084     ret->AddNode(a);
4085     return ret;
4086   }
4087 }
4088 
TanhLink(Expression a)4089 Expression TanhLink(Expression a)
4090 {
4091   // go for it
4092   if (a->IsLeaf() && a->GetOpType() == CONST)
4093   {
4094     a->SetValue(tanh(a->GetValue()));
4095     a->SetCoeff(1.0);
4096     a->SetExponent(1.0);
4097     a->SetOpType(CONST);
4098     return a;
4099   }
4100   else
4101   {
4102     Expression ret;
4103     ret->SetCoeff(1.0);
4104     ret->SetExponent(1.0);
4105     ret->SetOpType(TANH);
4106     ret->AddNode(a);
4107     return ret;
4108   }
4109 }
4110 
AsinhLink(Expression a)4111 Expression AsinhLink(Expression a)
4112 {
4113   // go for it
4114   if (a->IsLeaf() && a->GetOpType() == CONST)
4115   {
4116     a->SetValue(asinh(a->GetValue()));
4117     a->SetCoeff(1.0);
4118     a->SetExponent(1.0);
4119     a->SetOpType(CONST);
4120     return a;
4121   }
4122   else
4123   {
4124     Expression ret;
4125     ret->SetCoeff(1.0);
4126     ret->SetExponent(1.0);
4127     ret->SetOpType(ASINH);
4128     ret->AddNode(a);
4129     return ret;
4130   }
4131 }
4132 
AcoshLink(Expression a)4133 Expression AcoshLink(Expression a)
4134 {
4135   if (a->IsLessThan(1.0))
4136     throw ErrNotPermitted(0, "Expression Building", "AcoshLink", "value < 1", "acosh(<1) is undefined", HELPURL);
4137 
4138   // go for it
4139   if (a->IsLeaf() && a->GetOpType() == CONST)
4140   {
4141     a->SetValue(acosh(a->GetValue()));
4142     a->SetCoeff(1.0);
4143     a->SetExponent(1.0);
4144     a->SetOpType(CONST);
4145     return a;
4146   }
4147   else
4148   {
4149     Expression ret;
4150     ret->SetCoeff(1.0);
4151     ret->SetExponent(1.0);
4152     ret->SetOpType(ACOSH);
4153     ret->AddNode(a);
4154     return ret;
4155   }
4156 }
4157 
AtanhLink(Expression a)4158 Expression AtanhLink(Expression a)
4159 {
4160   if (a->IsLessThan(-1.0) || a->IsGreaterThan(1.0))
4161     throw ErrNotPermitted(0, "Expression Building", "AtanhLink", "value <-1|>1", "atanh(<-1|>1) is undefined", HELPURL);
4162 
4163   // go for it
4164   if (a->IsLeaf() && a->GetOpType() == CONST)
4165   {
4166     a->SetValue(atanh(a->GetValue()));
4167     a->SetCoeff(1.0);
4168     a->SetExponent(1.0);
4169     a->SetOpType(CONST);
4170     return a;
4171   }
4172   else
4173   {
4174     Expression ret;
4175     ret->SetCoeff(1.0);
4176     ret->SetExponent(1.0);
4177     ret->SetOpType(ATANH);
4178     ret->AddNode(a);
4179     return ret;
4180   }
4181 }
4182 
Log2Link(Expression a)4183 Expression Log2Link(Expression a)
4184 {
4185   // make a preliminary check
4186   if (a->IsZero())
4187     throw ErrNotPermitted(0, "Expression Building", "Log2Link", "IsZero()", "log2(0) is undefined", HELPURL);
4188 
4189   if (a->IsLessThan(0))
4190     throw ErrNotPermitted(0, "Expression Building", "Log2Link", "value <= 0", "log2(<=0) is undefined", HELPURL);
4191 
4192   // go for it
4193   if (a->IsLeaf() && a->GetOpType() == CONST)
4194   {
4195     double t = a->GetValue();
4196     assert(t >= 0);
4197     a->SetCoeff(1.0);
4198     a->SetValue(log2(t));
4199     a->SetExponent(1.0);
4200     a->SetOpType(CONST);
4201     return a;
4202   }
4203   else
4204   {
4205     Expression ret;
4206     ret->SetCoeff(1.0);
4207     ret->SetExponent(1.0);
4208     ret->SetOpType(LOG2);
4209     ret->AddNode(a);
4210     return ret;
4211   }
4212 }
4213 
Log10Link(Expression a)4214 Expression Log10Link(Expression a)
4215 {
4216   // make a preliminary check
4217   if (a->IsZero())
4218     throw ErrNotPermitted(0, "Expression Building", "Log10Link", "IsZero()", "log10(0) is undefined", HELPURL);
4219 
4220   if (a->IsLessThan(0))
4221     throw ErrNotPermitted(0, "Expression Building", "Log10Link", "value <= 0", "log10(<=0) is undefined", HELPURL);
4222 
4223   // go for it
4224   if (a->IsLeaf() && a->GetOpType() == CONST)
4225   {
4226     double t = a->GetValue();
4227     assert(t >= 0);
4228     a->SetCoeff(1.0);
4229     a->SetValue(log10(t));
4230     a->SetExponent(1.0);
4231     a->SetOpType(CONST);
4232     return a;
4233   }
4234   else
4235   {
4236     Expression ret;
4237     ret->SetCoeff(1.0);
4238     ret->SetExponent(1.0);
4239     ret->SetOpType(LOG10);
4240     ret->AddNode(a);
4241     return ret;
4242   }
4243 }
4244 
LogLink(Expression a)4245 Expression LogLink(Expression a)
4246 {
4247   // make a preliminary check
4248   if (a->IsZero())
4249     throw ErrNotPermitted(0, "Expression Building", "LogLink", "IsZero()", "log(0) is undefined", HELPURL);
4250 
4251   if (a->IsLessThan(0))
4252     throw ErrNotPermitted(0, "Expression Building", "LogLink", "value <= 0", "log(<=0) is undefined", HELPURL);
4253 
4254   // go for it
4255   if (a->IsLeaf() && a->GetOpType() == CONST)
4256   {
4257     double t = a->GetValue();
4258     assert(t >= 0);
4259     a->SetCoeff(1.0);
4260     a->SetValue(log(t));
4261     a->SetExponent(1.0);
4262     a->SetOpType(CONST);
4263     return a;
4264   }
4265   else
4266   {
4267     Expression ret;
4268     ret->SetCoeff(1.0);
4269     ret->SetExponent(1.0);
4270     ret->SetOpType(LOG);
4271     ret->AddNode(a);
4272     return ret;
4273   }
4274 }
4275 
LnLink(Expression a)4276 Expression LnLink(Expression a)
4277 {
4278   // make a preliminary check
4279   if (a->IsZero())
4280     throw ErrNotPermitted(0, "Expression Building", "LnLink", "IsZero()", "ln(0) is undefined", HELPURL);
4281 
4282   if (a->IsLessThan(0))
4283     throw ErrNotPermitted(0, "Expression Building", "LnLink", "value <= 0", "ln(<=0) is undefined", HELPURL);
4284 
4285   // go for it
4286   if (a->IsLeaf() && a->GetOpType() == CONST)
4287   {
4288     double t = a->GetValue();
4289     assert(t >= 0);
4290     a->SetCoeff(1.0);
4291     a->SetValue(log(t));
4292     a->SetExponent(1.0);
4293     a->SetOpType(CONST);
4294     return a;
4295   }
4296   else
4297   {
4298     Expression ret;
4299     ret->SetCoeff(1.0);
4300     ret->SetExponent(1.0);
4301     ret->SetOpType(LN);
4302     ret->AddNode(a);
4303     return ret;
4304   }
4305 }
4306 
LngammaLink(Expression a)4307 Expression LngammaLink(Expression a)
4308 {
4309   if (a->IsLessThan(0.0))
4310     throw ErrNotPermitted(0, "Expression Building", "LngammaLink", "value < 0", "lngamma(<0) is undefined", HELPURL);
4311 
4312   // go for it
4313   if (a->IsLeaf() && a->GetOpType() == CONST)
4314   {
4315     a->SetValue(lgamma(a->GetValue()));
4316     a->SetCoeff(1.0);
4317     a->SetExponent(1.0);
4318     a->SetOpType(CONST);
4319     return a;
4320   }
4321   else
4322   {
4323     Expression ret;
4324     ret->SetCoeff(1.0);
4325     ret->SetExponent(1.0);
4326     ret->SetOpType(LNGAMMA);
4327     ret->AddNode(a);
4328     return ret;
4329   }
4330 }
4331 
GammaLink(Expression a)4332 Expression GammaLink(Expression a)
4333 {
4334   // go for it
4335   if (a->IsLeaf() && a->GetOpType() == CONST)
4336   {
4337     a->SetValue(exp(lgamma(a->GetValue())));
4338     a->SetCoeff(1.0);
4339     a->SetExponent(1.0);
4340     a->SetOpType(CONST);
4341     return a;
4342   }
4343   else
4344   {
4345     Expression ret;
4346     ret->SetCoeff(1.0);
4347     ret->SetExponent(1.0);
4348     ret->SetOpType(GAMMA);
4349     ret->AddNode(a);
4350     return ret;
4351   }
4352 }
4353 
ExpLink(Expression a)4354 Expression ExpLink(Expression a)
4355 {
4356   // go for it
4357   if (a->IsLeaf() && a->GetOpType() == CONST)
4358   {
4359     a->SetValue(exp(a->GetValue()));
4360     a->SetCoeff(1.0);
4361     a->SetExponent(1.0);
4362     a->SetOpType(CONST);
4363     return a;
4364   }
4365   else
4366   {
4367     Expression ret;
4368     ret->SetCoeff(1.0);
4369     ret->SetExponent(1.0);
4370     ret->SetOpType(EXP);
4371     ret->AddNode(a);
4372     return ret;
4373   }
4374 }
4375 
ErfLink(Expression a)4376 Expression ErfLink(Expression a)
4377 {
4378   // go for it
4379   if (a->IsLeaf() && a->GetOpType() == CONST)
4380   {
4381     a->SetValue(erf(a->GetValue()));
4382     a->SetCoeff(1.0);
4383     a->SetExponent(1.0);
4384     a->SetOpType(CONST);
4385     return a;
4386   }
4387   else
4388   {
4389     Expression ret;
4390     ret->SetCoeff(1.0);
4391     ret->SetExponent(1.0);
4392     ret->SetOpType(ERF);
4393     ret->AddNode(a);
4394     return ret;
4395   }
4396 }
4397 
ErfcLink(Expression a)4398 Expression ErfcLink(Expression a)
4399 {
4400   // go for it
4401   if (a->IsLeaf() && a->GetOpType() == CONST)
4402   {
4403     a->SetValue(erfc(a->GetValue()));
4404     a->SetCoeff(1.0);
4405     a->SetExponent(1.0);
4406     a->SetOpType(CONST);
4407     return a;
4408   }
4409   else
4410   {
4411     Expression ret;
4412     ret->SetCoeff(1.0);
4413     ret->SetExponent(1.0);
4414     ret->SetOpType(ERFC);
4415     ret->AddNode(a);
4416     return ret;
4417   }
4418 }
4419 
SqrtLink(Expression a)4420 Expression SqrtLink(Expression a)
4421 {
4422   // make a preliminary check
4423   if (a->IsLessThan(0) && !a->HasValue(0))
4424     throw ErrNotPermitted(0, "Expression Building", "SqrtLink", "value < 0", "sqrt(<0) is complex, can't do", HELPURL);
4425 
4426   // go for it
4427   if (a->IsLeaf() && a->GetOpType() == CONST)
4428   {
4429     double t = a->GetValue();
4430     assert(t >= 0.);
4431     a->SetCoeff(1.0);
4432     a->SetValue(sqrt(t));
4433     a->SetExponent(1.0);
4434     a->SetOpType(CONST);
4435     return a;
4436   }
4437   else
4438   {
4439     Expression ret;
4440     ret->SetCoeff(1.0);
4441     ret->SetExponent(1.0);
4442     ret->SetOpType(SQRT);
4443     ret->AddNode(a);
4444     return ret;
4445   }
4446 }
4447 
CbrtLink(Expression a)4448 Expression CbrtLink(Expression a)
4449 {
4450   // go for it
4451   if (a->IsLeaf() && a->GetOpType() == CONST)
4452   {
4453     a->SetValue(cbrt(a->GetValue()));
4454     a->SetCoeff(1.0);
4455     a->SetExponent(1.0);
4456     a->SetOpType(CONST);
4457     return a;
4458   }
4459   else
4460   {
4461     Expression ret;
4462     ret->SetCoeff(1.0);
4463     ret->SetExponent(1.0);
4464     ret->SetOpType(CBRT);
4465     ret->AddNode(a);
4466     return ret;
4467   }
4468 }
4469 
BesselJ0Link(Expression a)4470 Expression BesselJ0Link(Expression a)
4471 {
4472   // go for it
4473   if (a->IsLeaf() && a->GetOpType() == CONST)
4474   {
4475     a->SetValue(j0(a->GetValue()));
4476     a->SetCoeff(1.0);
4477     a->SetExponent(1.0);
4478     a->SetOpType(CONST);
4479     return a;
4480   }
4481   else
4482   {
4483     Expression ret;
4484     ret->SetCoeff(1.0);
4485     ret->SetExponent(1.0);
4486     ret->SetOpType(BESSELJ0);
4487     ret->AddNode(a);
4488     return ret;
4489   }
4490 }
4491 
BesselJ1Link(Expression a)4492 Expression BesselJ1Link(Expression a)
4493 {
4494   // go for it
4495   if (a->IsLeaf() && a->GetOpType() == CONST)
4496   {
4497     a->SetValue(j1(a->GetValue()));
4498     a->SetCoeff(1.0);
4499     a->SetExponent(1.0);
4500     a->SetOpType(CONST);
4501     return a;
4502   }
4503   else
4504   {
4505     Expression ret;
4506     ret->SetCoeff(1.0);
4507     ret->SetExponent(1.0);
4508     ret->SetOpType(BESSELJ1);
4509     ret->AddNode(a);
4510     return ret;
4511   }
4512 }
4513 
BesselY0Link(Expression a)4514 Expression BesselY0Link(Expression a)
4515 {
4516   // go for it
4517   if (a->IsLeaf() && a->GetOpType() == CONST)
4518   {
4519     a->SetValue(y0(a->GetValue()));
4520     a->SetCoeff(1.0);
4521     a->SetExponent(1.0);
4522     a->SetOpType(CONST);
4523     return a;
4524   }
4525   else
4526   {
4527     Expression ret;
4528     ret->SetCoeff(1.0);
4529     ret->SetExponent(1.0);
4530     ret->SetOpType(BESSELY0);
4531     ret->AddNode(a);
4532     return ret;
4533   }
4534 }
4535 
BesselY1Link(Expression a)4536 Expression BesselY1Link(Expression a)
4537 {
4538   // go for it
4539   if (a->IsLeaf() && a->GetOpType() == CONST)
4540   {
4541     a->SetValue(y1(a->GetValue()));
4542     a->SetCoeff(1.0);
4543     a->SetExponent(1.0);
4544     a->SetOpType(CONST);
4545     return a;
4546   }
4547   else
4548   {
4549     Expression ret;
4550     ret->SetCoeff(1.0);
4551     ret->SetExponent(1.0);
4552     ret->SetOpType(BESSELY1);
4553     ret->AddNode(a);
4554     return ret;
4555   }
4556 }
4557 
SignLink(Expression a)4558 Expression SignLink(Expression a)
4559 {
4560   // go for it
4561   if (a->IsLeaf() && a->GetOpType() == CONST)
4562   {
4563     double tmp(a->GetValue());
4564     a->SetValue((tmp < 0) ? -1.0 : (tmp > 0) ? 1.0 : 0.0);
4565     a->SetCoeff(1.0);
4566     a->SetExponent(1.0);
4567     a->SetOpType(CONST);
4568     return a;
4569   }
4570   else
4571   {
4572     Expression ret;
4573     ret->SetCoeff(1.0);
4574     ret->SetExponent(1.0);
4575     ret->SetOpType(SIGN);
4576     ret->AddNode(a);
4577     return ret;
4578   }
4579 }
4580 
RintLink(Expression a)4581 Expression RintLink(Expression a)
4582 {
4583   // go for it
4584   if (a->IsLeaf() && a->GetOpType() == CONST)
4585   {
4586     a->SetValue(floor(0.5 + a->GetValue()));
4587     a->SetCoeff(1.0);
4588     a->SetExponent(1.0);
4589     a->SetOpType(CONST);
4590     return a;
4591   }
4592   else
4593   {
4594     Expression ret;
4595     ret->SetCoeff(1.0);
4596     ret->SetExponent(1.0);
4597     ret->SetOpType(RINT);
4598     ret->AddNode(a);
4599     return ret;
4600   }
4601 }
4602 
AbsLink(Expression a)4603 Expression AbsLink(Expression a)
4604 {
4605   // go for it
4606   if (a->IsLeaf() && a->GetOpType() == CONST)
4607   {
4608     a->SetValue(std::abs(a->GetValue()));
4609     a->SetCoeff(1.0);
4610     a->SetExponent(1.0);
4611     a->SetOpType(CONST);
4612     return a;
4613   }
4614   else
4615   {
4616     Expression ret;
4617     ret->SetCoeff(1.0);
4618     ret->SetExponent(1.0);
4619     ret->SetOpType(ABS);
4620     ret->AddNode(a);
4621     return ret;
4622   }
4623 }
4624 
CotLink(Expression a)4625 Expression CotLink(Expression a)
4626 {
4627   // make a preliminary check
4628   if (a->IsZero())
4629     throw ErrNotPermitted(0, "Expression Building", "CotLink", "IsZero()", "cot(0) is undefined", HELPURL);
4630 
4631   // go for it
4632   if (a->IsLeaf() && a->GetOpType() == CONST)
4633   {
4634     double t = tan(a->GetValue());
4635     assert(t != 0);
4636     a->SetCoeff(1.0);
4637     a->SetValue(1 / t);
4638     a->SetExponent(1.0);
4639     a->SetOpType(CONST);
4640     return a;
4641   }
4642   else
4643   {
4644     Expression ret;
4645     ret->SetCoeff(1.0);
4646     ret->SetExponent(1.0);
4647     ret->SetOpType(COT);
4648     ret->AddNode(a);
4649     return ret;
4650   }
4651 }
4652 
CothLink(Expression a)4653 Expression CothLink(Expression a)
4654 {
4655   // make a preliminary check
4656   if (a->IsZero())
4657     throw ErrNotPermitted(0, "Expression Building", "CothLink", "IsZero()", "coth(0) is undefined", HELPURL);
4658 
4659   // go for it
4660   if (a->IsLeaf() && a->GetOpType() == CONST)
4661   {
4662     double t = tanh(a->GetValue());
4663     assert(t != 0);
4664     a->SetCoeff(1.0);
4665     a->SetValue(1 / t);
4666     a->SetExponent(1.0);
4667     a->SetOpType(CONST);
4668     return a;
4669   }
4670   else
4671   {
4672     Expression ret;
4673     ret->SetCoeff(1.0);
4674     ret->SetExponent(1.0);
4675     ret->SetOpType(COTH);
4676     ret->AddNode(a);
4677     return ret;
4678   }
4679 }
4680 
4681 
4682 /***************** differentiation ******************/
4683 
4684 // differentiate w.r.t. variable varindex
Diff(const Expression & ac,Int vi)4685 Expression Diff(const Expression& ac, Int vi)
4686 {
4687   Expression ret(DiffNoSimplify(ac, vi));
4688   Simplify(&ret);
4689   return ret;
4690 }
4691 
DiffNoSimplify(const Expression & ac,Int vi)4692 Expression DiffNoSimplify(const Expression& ac, Int vi)
4693 {
4694   Expression a;
4695   a.SetToCopyOf(ac);
4696   Expression zero(0.0);
4697   Expression c(1.0);
4698   if (a->DependsOnVariable(vi))
4699   {
4700     if (a->IsLeaf())
4701     {
4702       if (a->GetOpType() == CONST || a->GetVarIndex() != vi)
4703       {
4704         // safety check
4705         std::cerr << "Expression::Diff: warning: this node should "
4706                   << "not diff to zero\n";
4707         return zero;
4708       }
4709       else
4710       {
4711         // variable vi, check exponent
4712         if (a->GetExponent() == 0)
4713         {
4714           // exponent is zero, node is actually constant
4715           return zero;
4716         }
4717         else if (a->GetExponent() == 1)
4718         {
4719           // exponent is one, node is variable
4720           c->SetValue(a->GetCoeff());
4721 
4722           return c;
4723         }
4724         else
4725         {
4726           // for all other cases, apply rule x^c = c*x^(c-1)
4727           double expon = a->GetExponent();
4728           Expression ret(a.Copy());
4729           ret->SetExponent(expon - 1);
4730           ret->SetCoeff(ret->GetCoeff() * expon);
4731           return ret;
4732         }
4733       }
4734     }
4735     else
4736     {
4737 
4738       // non-leaf node. build derivative.
4739       int op = a->GetOpType();
4740       Int sz = a->GetSize();
4741       double opcoeff = a->GetCoeff();
4742       if (sz == 0)
4743       {
4744         throw ErrNotPermitted(10, "Expression", "Diff", "GetSize() == 0",
4745                               "non-leaf node can't have size 0", HELPURL);
4746       }
4747       Int i, j;
4748       Expression ret(0.0);
4749       Expression tmp(1.0);
4750       Expression tmp2(1.0);
4751       Expression two(2.0);
4752       switch(op)
4753       {
4754         case SUM:
4755           ret = Diff(a->GetNode(0), vi); // f_0'
4756           for(i = 1; i < sz; i++)
4757           {
4758             tmp = Diff(a->GetNode(i), vi);
4759             if (!tmp->IsZero())
4760             {
4761               ret = ret + tmp; // ... + g_i'
4762             }
4763           }
4764           break;
4765         case DIFFERENCE:
4766           ret = Diff(a->GetNode(0), vi);  // f_0'
4767           for(i = 1; i < sz; i++)
4768           {
4769             tmp = Diff(a->GetNode(i), vi);
4770             if (!tmp->IsZero())
4771             {
4772               ret = ret - tmp;  // ... - g_i'
4773             }
4774           }
4775           break;
4776         case PRODUCT:
4777           if (sz == 1)
4778           {
4779             // warn about product with one operand
4780             std::cerr << "Expression::Diff: warning: product with 1 operand "
4781                       << "should not occur\n";
4782           }
4783           ret = Diff(a->GetNode(0), vi);  // f_0'
4784           if (!ret->IsZero())
4785           {
4786             for(j = 1; j < sz; j++)
4787             {
4788               // get copies, not references
4789               ret = ret * a->GetCopyOfNode(j); // ... * f_i[i!=0]
4790             }
4791           }
4792           tmp->One(); // reset temporary to 1.0
4793           for(i = 1; i < sz; i++)
4794           {
4795             tmp = Diff(a->GetNode(i), vi); // tmp = f_i'
4796             if (!tmp->IsZero())
4797             {
4798               for(j = 0; j < sz; j++)
4799               {
4800                 if (j != i)
4801                 {
4802                   // get references, and copy later (in sum)
4803                   tmp = tmp * a->GetNode(j); // ... * f_j[i!=i]
4804                 }
4805               }
4806               ret = ret + tmp.Copy();  // ... + tmp
4807               tmp->One(); // reset temporary to 1.0
4808             }
4809           }
4810           break;
4811         case FRACTION:
4812           if (sz != 2)
4813           {
4814             // check that there are exactly two operands
4815             throw ErrNotPermitted(11, "Expression", "Diff", "GetSize() != 2",
4816                                   "fraction must have exactly 2 operands",
4817                                   HELPURL);
4818           }
4819           if (a->GetNode(1)->IsZero())
4820           {
4821             // check denominator is not zero
4822             throw ErrDivideByZero(20, "Expression", "Diff",
4823                                   "GetNode(1)->IsZero()",
4824                                   "cannot divide by zero", HELPURL,
4825                                   a->GetNode(1)->ToString());
4826           }
4827           tmp->One();
4828           ret = Diff(a->GetNode(0), vi); // f'
4829           if (!ret->IsZero())
4830           {
4831             ret = ret / a->GetCopyOfNode(1);  // f'/g
4832           }
4833           // can dispense from using GetCopyOf because tmp gets copied anyway
4834           tmp = a->GetNode(0);           // tmp = f
4835           tmp2 = Diff(a->GetNode(1), vi);
4836           if (!tmp2->IsZero())
4837           {
4838             tmp = tmp * tmp2;  // tmp = fg'
4839             ret = ret - tmp.Copy() / (a->GetCopyOfNode(1) ^ two);  // f'/g - fg'/g^2
4840           }
4841           // can dispense from using copy here - tmp is not used thereafter
4842           // and when tmp is deleted, its subnodes are not automatically
4843           // deleted unless reference counter is zero - which won't be.
4844           break;
4845         case POWER:
4846           if (sz != 2)
4847           {
4848             // check that there are exactly two operands
4849             throw ErrNotPermitted(12, "Expression", "Diff", "GetSize() != 2",
4850                                   "power must have exactly 2 operands",
4851                                   HELPURL);
4852           }
4853           // check exponent
4854           if (a->GetNode(1)->IsZero())
4855           {
4856             // exponent is zero, whole node is one, diff is zero
4857             ret->Zero();
4858           }
4859           else if (a->GetNode(1)->HasValue(1.0))
4860           {
4861             // exponent is one, whole node is first operand, diff
4862             // is diff of first operand
4863             ret = Diff(a->GetNode(0), vi);
4864           }
4865           else if (a->GetNode(1)->HasValue(2.0))
4866           {
4867             // exponent is two, diff is 2 * first op * diff of first operand
4868             ret = Diff(a->GetNode(0), vi);  // f'
4869             ret = ret * a->GetCopyOfNode(0);   // f'f
4870             ret->SetCoeff(ret->GetCoeff() * 2.0);  // 2f'f
4871           }
4872           else
4873           {
4874             // all other cases
4875             if (a->GetNode(1)->IsConstant())
4876             {
4877               // numeric exponent != 0,1,2
4878               ret = Diff(a->GetNode(0), vi); // f'
4879               tmp = a->GetCopyOfNode(0);     // f
4880               const double coeff = tmp->GetCoeff();
4881               tmp = tmp ^ a->GetCopyOfNode(1);  // f^c
4882               if (tmp->GetOpType() == VAR)
4883               {
4884                 tmp->SetCoeff(tmp->GetExponent() * std::pow(coeff, tmp->GetExponent() - 1.0)); // cf^c
4885                 tmp->SetExponent(tmp->GetExponent() - 1); // cf^(c-1)
4886               }
4887               else
4888               {
4889                 tmp->GetNode(1)->ConsolidateValue();
4890                 tmp->SetCoeff(tmp->GetCoeff() * tmp->GetNode(1)->GetValue());//cf^c
4891                 tmp->GetNode(1)->SetValue(tmp->GetNode(1)->GetValue() - 1); //cf^(c-1)
4892               }
4893               // can dispense from using copy here - Diff returns copies anyway.
4894               // when temporary is deleted, its subnodes are not automatically
4895               // deleted unless their reference counter is zero - which won't be.
4896               ret = ret * tmp; // f'(cf^(c-1))
4897             }
4898             else
4899             {
4900               // symbolic exponent f^g
4901               ret = a->GetCopyOfNode(0); // f
4902               ret = Log(ret); // log(f)
4903               // can dispense from using copy here - Diff returns copies anyway.
4904               // when temporary is deleted, its subnodes are not automatically
4905               // deleted unless their reference counter is zero - which won't be.
4906               ret = ret * Diff(a->GetNode(1), vi); // g' log(f)
4907               tmp = Diff(a->GetNode(0), vi);  // f'
4908               tmp = tmp * a->GetCopyOfNode(1);   // gf'
4909               tmp = tmp / a->GetCopyOfNode(0);    // gf'/f
4910               // can dispense from using copy here - tmp is not used thereafter
4911               // and when tmp is deleted, its subnodes are not automatically
4912               // deleted unless their reference counter is zero - which won't be.
4913               ret = ret + tmp;           // g'log(f) + gf'/f
4914               tmp = a.Copy();
4915               tmp->SetCoeff(1.0);
4916               ret = ret * tmp;        // (g'log(f) + gf'/f)(f^g)
4917             }
4918           }
4919           break;
4920         case MINUS:
4921           if (sz != 1)
4922           {
4923             // check that there is exactly one operand
4924             throw ErrNotPermitted(13, "Expression", "Diff", "GetSize() != 1",
4925                                   "unary minus must have exactly 1 operand",
4926                                   HELPURL);
4927           }
4928           ret = Diff(a->GetNode(0), vi);
4929           ret->SetCoeff(- ret->GetCoeff());
4930           break;
4931         case SIN:
4932           if (sz != 1)
4933           {
4934             // check that there is exactly one operand
4935             throw ErrNotPermitted(17, "Expression", "Diff", "GetSize() != 1",
4936                                   "sin must have exactly 1 operand",
4937                                   HELPURL);
4938           }
4939           ret = Diff(a->GetNode(0), vi) * Cos(a->GetCopyOfNode(0));  // f' cos(f)
4940           break;
4941         case COS:
4942           if (sz != 1)
4943           {
4944             // check that there is exactly one operand
4945             throw ErrNotPermitted(18, "Expression", "Diff", "GetSize() != 1",
4946                                   "cos must have exactly 1 operand",
4947                                   HELPURL);
4948           }
4949           ret = -Diff(a->GetNode(0), vi) * Sin(a->GetCopyOfNode(0)); // -f'sin(f)
4950           break;
4951         case TAN:
4952           if (sz != 1)
4953           {
4954             // check that there is exactly one operand
4955             throw ErrNotPermitted(19, "Expression", "Diff", "GetSize() != 1",
4956                                   "tan must have exactly 1 operand",
4957                                   HELPURL);
4958           }
4959           ret = a.Copy();  // tan(f)
4960           ret->SetCoeff(1.0);
4961           ret = ret ^ two;      // tan(f)^2
4962           c->One();
4963           ret = ret + c;         // tan(f)^2 + 1
4964           ret = ret * Diff(a->GetNode(0), vi);    // f' * (tan(f)^2 + 1)
4965           break;
4966         case ASIN:
4967           if (sz != 1)
4968           {
4969             // check that there is exactly one operand
4970             throw ErrNotPermitted(17, "Expression", "Diff", "GetSize() != 1",
4971                                   "asin must have exactly 1 operand",
4972                                   HELPURL);
4973           }
4974           ret = a->GetCopyOfNode(0);
4975           ret = ret ^ two;
4976           c->One();
4977           ret = c - ret;
4978           ret = Diff(a->GetNode(0), vi) / Sqrt(ret); // f' / sqrt(1 - f^2)
4979           break;
4980         case ACOS:
4981           if (sz != 1)
4982           {
4983             // check that there is exactly one operand
4984             throw ErrNotPermitted(18, "Expression", "Diff", "GetSize() != 1",
4985                                   "acos must have exactly 1 operand",
4986                                   HELPURL);
4987           }
4988           ret = a->GetCopyOfNode(0);
4989           ret = ret ^ two;
4990           c->One();
4991           ret = c - ret;
4992           ret = -Diff(a->GetNode(0), vi) / Sqrt(ret); // -f' / sqrt(1 - f^2)
4993           break;
4994         case ATAN:
4995           if (sz != 1)
4996           {
4997             // check that there is exactly one operand
4998             throw ErrNotPermitted(19, "Expression", "Diff", "GetSize() != 1",
4999                                   "atan must have exactly 1 operand",
5000                                   HELPURL);
5001           }
5002           ret = a->GetCopyOfNode(0);
5003           ret = ret ^ two;
5004           c->One();
5005           ret = ret + c;
5006           ret = Diff(a->GetNode(0), vi) / ret; // f' / (f^2 + 1)
5007           break;
5008         case SINH:
5009           if (sz != 1)
5010           {
5011             // check that there is exactly one operand
5012             throw ErrNotPermitted(17, "Expression", "Diff", "GetSize() != 1",
5013                                   "sinh must have exactly 1 operand",
5014                                   HELPURL);
5015           }
5016           ret = Diff(a->GetNode(0), vi) * Cosh(a->GetCopyOfNode(0));  // f' cosh(f)
5017           break;
5018         case COSH:
5019           if (sz != 1)
5020           {
5021             // check that there is exactly one operand
5022             throw ErrNotPermitted(18, "Expression", "Diff", "GetSize() != 1",
5023                                   "cosh must have exactly 1 operand",
5024                                   HELPURL);
5025           }
5026           ret = Diff(a->GetNode(0), vi) * Sinh(a->GetCopyOfNode(0)); // f'sinh(f)
5027           break;
5028         case TANH:
5029           if (sz != 1)
5030           {
5031             // check that there is exactly one operand
5032             throw ErrNotPermitted(19, "Expression", "Diff", "GetSize() != 1",
5033                                   "tanh must have exactly 1 operand",
5034                                   HELPURL);
5035           }
5036           ret = a.Copy();
5037           ret->SetCoeff(1.0);
5038           ret = ret ^ two;
5039           c->One();
5040           ret = c - ret;
5041           ret = ret * Diff(a->GetNode(0), vi);    // f' * (1 - tan(f)^2)
5042           break;
5043         case ASINH:
5044           if (sz != 1)
5045           {
5046             // check that there is exactly one operand
5047             throw ErrNotPermitted(17, "Expression", "Diff", "GetSize() != 1",
5048                                   "asinh must have exactly 1 operand",
5049                                   HELPURL);
5050           }
5051           ret = a->GetCopyOfNode(0);
5052           ret = ret ^ two;
5053           c->One();
5054           ret = c + ret;
5055           ret = Diff(a->GetNode(0), vi) / Sqrt(ret); // f' / sqrt(1 + f^2)
5056           break;
5057         case ACOSH:
5058           if (sz != 1)
5059           {
5060             // check that there is exactly one operand
5061             throw ErrNotPermitted(18, "Expression", "Diff", "GetSize() != 1",
5062                                   "acosh must have exactly 1 operand",
5063                                   HELPURL);
5064           }
5065           ret = a->GetCopyOfNode(0);
5066           ret = ret ^ two;
5067           c->One();
5068           ret = ret - c;
5069           ret = Diff(a->GetNode(0), vi) / Sqrt(ret); // f' / sqrt(f^2 - 1)
5070           break;
5071         case ATANH:
5072           if (sz != 1)
5073           {
5074             // check that there is exactly one operand
5075             throw ErrNotPermitted(19, "Expression", "Diff", "GetSize() != 1",
5076                                   "atanh must have exactly 1 operand",
5077                                   HELPURL);
5078           }
5079           ret = a->GetCopyOfNode(0);
5080           ret = ret ^ two;
5081           c->One();
5082           ret = c - ret;
5083           ret = Diff(a->GetNode(0), vi) / ret;    // f' / (1 - tan(f)^2)
5084           break;
5085         case LOG2:
5086           if (sz != 1)
5087           {
5088             // check that there is exactly one operand
5089             throw ErrNotPermitted(14, "Expression", "Diff", "GetSize() != 1",
5090                                   "log2 must have exactly 1 operand",
5091                                   HELPURL);
5092           }
5093           if (a->GetNode(0)->IsLessThan(0))
5094           {
5095             throw ErrNotPermitted(15, "Expression", "Diff", "arg <= 0",
5096                                   "log2 argument must be symbolic or positive",
5097                                   HELPURL);
5098           }
5099           ret = Diff(a->GetNode(0), vi);
5100           ret = ret / (Expression(M_LN2) * a->GetCopyOfNode(0));  // f'/(log(2)f)
5101           break;
5102         case LOG10:
5103           if (sz != 1)
5104           {
5105             // check that there is exactly one operand
5106             throw ErrNotPermitted(14, "Expression", "Diff", "GetSize() != 1",
5107                                   "log10 must have exactly 1 operand",
5108                                   HELPURL);
5109           }
5110           if (a->GetNode(0)->IsLessThan(0))
5111           {
5112             throw ErrNotPermitted(15, "Expression", "Diff", "arg <= 0",
5113                                   "log10 argument must be symbolic or positive",
5114                                   HELPURL);
5115           }
5116           ret = Diff(a->GetNode(0), vi);
5117           ret = ret / (Expression(M_LN10) * a->GetCopyOfNode(0));  // f'/(log(10)f)
5118           break;
5119         case LOG:
5120         case LN:
5121           if (sz != 1)
5122           {
5123             // check that there is exactly one operand
5124             throw ErrNotPermitted(14, "Expression", "Diff", "GetSize() != 1",
5125                                   "log (ln) must have exactly 1 operand",
5126                                   HELPURL);
5127           }
5128           if (a->GetNode(0)->IsLessThan(0))
5129           {
5130             throw ErrNotPermitted(15, "Expression", "Diff", "arg <= 0",
5131                                   "log (ln) argument must be symbolic or positive",
5132                                   HELPURL);
5133           }
5134           ret = Diff(a->GetNode(0), vi);
5135           ret = ret / a->GetCopyOfNode(0);  // f'/f
5136           break;
5137         case EXP:
5138           if (sz != 1)
5139           {
5140             // check that there is exactly one operand
5141             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5142                                   "exp must have exactly 1 operand",
5143                                   HELPURL);
5144           }
5145           ret = Diff(a->GetNode(0), vi) * Exp(a->GetCopyOfNode(0));  // f'exp(f)
5146           break;
5147         case ERF:
5148           if (sz != 1)
5149           {
5150             // check that there is exactly one operand
5151             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5152                                   "erf must have exactly 1 operand",
5153                                   HELPURL);
5154           }
5155           ret = Expression(M_2_SQRTPI) * Diff(a->GetCopyOfNode(0), vi) * Exp(-(a->GetCopyOfNode(0) ^ two)); // (2/sqrt(pi)) f'e^(-f^2)
5156           break;
5157         case ERFC:
5158           if (sz != 1)
5159           {
5160             // check that there is exactly one operand
5161             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5162                                   "erfc must have exactly 1 operand",
5163                                   HELPURL);
5164           }
5165           ret = Expression(-M_2_SQRTPI) * Diff(a->GetCopyOfNode(0), vi) * Exp(-(a->GetCopyOfNode(0) ^ two)); // (2/sqrt(pi)) f'e^(-f^2)
5166           break;
5167         case SQRT:
5168           if (sz != 1)
5169           {
5170             // check that there is exactly one operand
5171             throw ErrNotPermitted(19, "Expression", "Diff", "GetSize() != 1",
5172                                   "sqrt must have exactly 1 operand",
5173                                   HELPURL);
5174           }
5175           if (a->GetNode(0)->IsLessThan(0))
5176           {
5177             throw ErrNotPermitted(15, "Expression", "Diff", "arg < 0",
5178                                   "sqrt argument must be symbolic or positive",
5179                                   HELPURL);
5180           }
5181           ret = Expression(0.5) * Diff(a->GetNode(0), vi) / Sqrt(a->GetCopyOfNode(0)); // 1/2 * f' / sqrt(f)
5182           break;
5183         case CBRT:
5184           if (sz != 1)
5185           {
5186             // check that there is exactly one operand
5187             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5188                                   "cbrt must have exactly 1 operand",
5189                                   HELPURL);
5190           }
5191           ret = Expression(1.0 / 3.0) * Diff(a->GetNode(0), vi) / (a->GetCopyOfNode(0) ^ Expression(2.0 / 3.0)); // (1/3) f' / f^(2/3)
5192           break;
5193         case BESSELJ0:
5194           if (sz != 1)
5195           {
5196             // check that there is exactly one operand
5197             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5198                                   "besselJ0 must have exactly 1 operand",
5199                                   HELPURL);
5200           }
5201           ret = -Diff(a->GetNode(0), vi) * BesselJ1(a->GetCopyOfNode(0)); // -f'besselJ1(f)
5202           break;
5203         case BESSELJ1:
5204           if (sz != 1)
5205           {
5206             // check that there is exactly one operand
5207             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5208                                   "besselJ1 must have exactly 1 operand",
5209                                   HELPURL);
5210           }
5211           ret = a->GetCopyOfNode(0);
5212           ret = BesselJ0(ret) - BesselJ1(ret) / ret;
5213           ret = Diff(a->GetNode(0), vi) * ret; // f'(besselJ0(f) - besselJ1(f) / f)
5214           break;
5215         case BESSELY0:
5216           if (sz != 1)
5217           {
5218             // check that there is exactly one operand
5219             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5220                                   "besselY0 must have exactly 1 operand",
5221                                   HELPURL);
5222           }
5223           ret = -Diff(a->GetNode(0), vi) * BesselY1(a->GetCopyOfNode(0)); // -f'besselY1(f)
5224           break;
5225         case BESSELY1:
5226           if (sz != 1)
5227           {
5228             // check that there is exactly one operand
5229             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5230                                   "besselY1 must have exactly 1 operand",
5231                                   HELPURL);
5232           }
5233           ret = a->GetCopyOfNode(0);
5234           ret = BesselY0(ret) - BesselY1(ret) / ret;
5235           ret = Diff(a->GetNode(0), vi) * ret; // f'(besselY0(f) - besselY1(f) / f)
5236           break;
5237         case SIGN:
5238         case RINT:
5239           if (sz != 1)
5240           {
5241             // check that there is exactly one operand
5242             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5243                                   "sign (rint) must have exactly 1 operand",
5244                                   HELPURL);
5245           }
5246           ret = zero; // 0
5247           break;
5248         case ABS:
5249           if (sz != 1)
5250           {
5251             // check that there is exactly one operand
5252             throw ErrNotPermitted(16, "Expression", "Diff", "GetSize() != 1",
5253                                   "abs must have exactly 1 operand",
5254                                   HELPURL);
5255           }
5256           ret = Diff(a->GetNode(0), vi) * Sign(a->GetCopyOfNode(0)); // f'sign(f)
5257           break;
5258         default:
5259           if (sz != 1)
5260           {
5261             // check that there is exactly one operand
5262             throw ErrNotPermitted(14, "Expression", "Diff", "GetSize() != 1",
5263                                   "log must have exactly 1 operand",
5264                                   HELPURL);
5265           }
5266           throw ErrNotPermitted(16, "Expression", "Diff", "not implemented",
5267                                 "The derivative of the function is not implemented.",
5268                                 HELPURL);
5269           break;
5270       }
5271       ret->SetCoeff(ret->GetCoeff() * opcoeff);
5272       return ret;
5273     }
5274   }
5275   else
5276   {
5277     return zero;
5278   }
5279   return zero;
5280 }
5281 
5282 /************************ simplifications **********************/
5283 
TrigSimp(Expression a)5284 bool TrigSimp(Expression a)
5285 {
5286   Int i = 0;
5287   Int ret = 0;
5288   bool bret = false;
5289   bool ischanged = false;
5290   // first, recurse over all subnodes of a
5291   for(i = 0; i < a->GetSize(); i++)
5292   {
5293     ischanged = TrigSimp(a->GetNode(i));
5294     if (!bret && ischanged)
5295     {
5296       bret = true;
5297     }
5298   }
5299   // now try simplification on a
5300   if (a->GetOpType() == SUM && a->GetSize() > 1)
5301   {
5302     // try to look for a sin^2 and a cos^2
5303     Int sinpos = -1;
5304     Int cospos = -1;
5305     Int sinpossimple = -1;
5306     Int cospossimple = -1;
5307     for (i = 0; i < a->GetSize(); i++)
5308     {
5309       // cycle over subnodes
5310       if (a->GetNode(i)->GetOpType() == POWER)
5311       {
5312         if (a->GetNode(i)->GetNode(0)->GetOpType() == SIN &&
5313             a->GetNode(i)->GetNode(1)->HasValue(2))
5314           sinpos = i;
5315       }
5316       if (a->GetNode(i)->GetOpType() == POWER)
5317       {
5318         if (a->GetNode(i)->GetNode(0)->GetOpType() == COS &&
5319             a->GetNode(i)->GetNode(1)->HasValue(2))
5320           cospos = i;
5321       }
5322       if (a->GetNode(i)->GetOpType() == SIN &&
5323           a->GetNode(i)->GetExponent() == 2)
5324       {
5325         sinpossimple = i;
5326       }
5327       if (a->GetNode(i)->GetOpType() == COS &&
5328           a->GetNode(i)->GetExponent() == 2)
5329       {
5330         cospossimple = i;
5331       }
5332     }
5333 
5334     if (sinpos != -1 && cospos != -1)
5335     {
5336       double coscoeff = a->GetNode(sinpos)->GetCoeff();
5337       double sincoeff = a->GetNode(cospos)->GetCoeff();
5338 
5339       // found both, check their arguments
5340       if ((coscoeff == sincoeff) &&
5341           a->GetNode(sinpos)->GetNode(0)->GetNode(0)->IsEqualTo
5342           (a->GetNode(cospos)->GetNode(0)->GetNode(0)))
5343       {
5344         ret++; // augment simplification counter
5345         bret = true;
5346         // arguments are equal, can simplify
5347         Int f = sinpos < cospos ? sinpos : cospos; // last to delete
5348         Int l = sinpos > cospos ? sinpos : cospos; // first to delete
5349         a->DeleteNode(l);
5350         a->DeleteNode(f);
5351         // verify that there are still some nodes left
5352         if (a->GetSize() == 0)
5353         {
5354           // there aren't any, set a to one
5355           a->One();
5356           a->SetCoeff(coscoeff);
5357         }
5358         else
5359         {
5360           // there are some, check whether there is a constant part
5361           // we can add the 1 to
5362           bool addflag = false;
5363           for (i = 0; i < a->GetSize(); i++)
5364           {
5365             if (a->GetNode(i)->IsConstant())
5366             {
5367               // yes there is
5368               a->GetNode(i)->SetValue(a->GetNode(i)->GetSimpleValue() + 1);
5369               addflag = true;
5370               break;
5371             }
5372           }
5373           if (!addflag)
5374           {
5375             // no there wasn't, add it as a symbolic node
5376             Expression coeffexpr(coscoeff);
5377             a->AddNode(coeffexpr);
5378           }
5379           // check that there is more than just one node
5380           if (a->GetSize() == 1)
5381           {
5382             // only one node, shift everything one rank level up
5383             a = a->GetNode(0);
5384           }
5385         }
5386       }
5387     }
5388     if (sinpossimple != -1 && cospossimple != -1)
5389     {
5390       double coscoeff = a->GetNode(sinpossimple)->GetCoeff();
5391       double sincoeff = a->GetNode(cospossimple)->GetCoeff();
5392 
5393       if ((coscoeff == sincoeff) &&
5394           a->GetNode(sinpossimple)->GetNode(0)->IsEqualTo
5395           (a->GetNode(cospossimple)->GetNode(0)))
5396       {
5397         ret++;
5398         bret = true;
5399         // arguments are equal, can simplify
5400         Int f = sinpossimple < cospossimple ? sinpossimple : cospossimple;
5401         Int l = sinpossimple > cospossimple ? sinpossimple : cospossimple;
5402         a->DeleteNode(l);
5403         a->DeleteNode(f);
5404         // verify that there are still some nodes left
5405         if (a->GetSize() == 0)
5406         {
5407           // there aren't any, set a to one
5408           a->One();
5409           a->SetCoeff(coscoeff);
5410         }
5411         else
5412         {
5413           // there are some, check whether there is a constant part
5414           // we can add the 1 to
5415           bool addflag = false;
5416           for (i = 0; i < a->GetSize(); i++)
5417           {
5418             if (a->GetNode(i)->IsConstant())
5419             {
5420               // yes there is
5421               a->GetNode(i)->SetValue(a->GetNode(i)->GetSimpleValue() + 1);
5422               addflag = true;
5423               break;
5424             }
5425           }
5426           if (!addflag)
5427           {
5428             // no there wasn't, add it as a symbolic node
5429             Expression coeffexpr(coscoeff);
5430             a->AddNode(coeffexpr);
5431           }
5432           // check that there is more than just one node
5433           if (a->GetSize() == 1)
5434           {
5435             // only one node, shift everything one rank level up
5436             a = a->GetNode(0);
5437           }
5438         }
5439       }
5440     }
5441   }
5442   if (ret > 0)
5443     bret = true;
5444   return bret;
5445 }
5446 
5447 // generic simplification with modification of the expression
Simplify(Expression * a)5448 bool Simplify(Expression* a)
5449 {
5450   bool changedflag = false;
5451   bool ret = false;
5452   bool goonflag = true;
5453   while(goonflag)
5454   {
5455     goonflag = false;
5456     (*a)->ConsolidateProductCoeffs();
5457     (*a)->DistributeCoeffOverSum();
5458     ret = DifferenceToSum(a);
5459     if (ret)
5460     {
5461       changedflag = true;
5462       goonflag = true;
5463     }
5464     ret = SimplifyConstant(a);
5465     if (ret)
5466     {
5467       changedflag = true;
5468       goonflag = true;
5469     }
5470     ret = CompactProducts(a);
5471     if (ret)
5472     {
5473       changedflag = true;
5474       goonflag = true;
5475     }
5476     ret = CompactLinearPart(a);
5477     if (ret)
5478     {
5479       changedflag = true;
5480       goonflag = true;
5481     }
5482     ret = SimplifyRecursive(a);
5483     if (ret)
5484     {
5485       changedflag = true;
5486       goonflag = true;
5487     }
5488     ret = TrigSimp(*a);
5489     if (ret)
5490     {
5491       changedflag = true;
5492       goonflag = true;
5493     }
5494   }
5495   return changedflag;
5496 }
5497 
5498 // call after DifferenceToSum
SimplifyConstant(Expression * a)5499 bool SimplifyConstant(Expression* a)
5500 {
5501   bool ret = false;
5502   Expression one(1.0);
5503   Expression zero(0.0);
5504   if ((*a)->GetExponent() == 0)
5505   {
5506     double c = (*a)->GetCoeff();
5507     RecursiveDestroy(a);
5508     a->SetTo(one);
5509     (*a)->SetCoeff(c);
5510     ret = true;
5511   }
5512   else if ((*a)->GetCoeff() == 0)
5513   {
5514     RecursiveDestroy(a);
5515     a->SetTo(zero);
5516     ret = true;
5517   }
5518   else
5519   {
5520     int i = 0;
5521     int op, ops;
5522     op = (*a)->GetOpType();
5523     bool ischanged = false;
5524     int sz = (*a)->GetSize();
5525     while (i < sz)
5526     {
5527       // simplify each of the terms
5528       ischanged = SimplifyConstant((*a)->GetNodePtr(i));
5529       if (!ret && ischanged)
5530       {
5531         ret = true;
5532       }
5533       i++;
5534     }
5535     i = 0;
5536     while (i < sz)
5537     {
5538       // simplify this operand as a whole
5539       ops = (*a)->GetNode(i)->GetOpType();
5540       switch(op)
5541       {
5542         case SUM:
5543           if (ops == CONST)
5544           {
5545             if ((*a)->GetNode(i)->GetValue() == 0)
5546             {
5547               (*a)->DeleteNode(i);
5548               ret = true;
5549               sz--;
5550               if (sz == 1)
5551               {
5552                 a->SetTo((*a)->GetNode(1 - i));
5553                 i = 0;
5554                 sz = (*a)->GetSize();
5555               }
5556             }
5557             else
5558             {
5559               i++;
5560             }
5561           }
5562           else
5563           {
5564             i++;
5565           }
5566           break;
5567         case PRODUCT:
5568           if (ops == CONST)
5569           {
5570             if ((*a)->GetNode(i)->GetValue() == 1)
5571             {
5572               (*a)->DeleteNode(i);
5573               ret = true;
5574               sz--;
5575               if (sz == 1)
5576               {
5577                 a->SetTo((*a)->GetNode(1 - i));
5578                 i = 0;
5579                 sz = (*a)->GetSize();
5580               }
5581             }
5582             else if ((*a)->GetNode(i)->GetValue() == 0)
5583             {
5584               RecursiveDestroy(a);
5585               ret = true;
5586               a->SetTo(zero);
5587               sz = 0;
5588             }
5589             else
5590             {
5591               i++;
5592             }
5593           }
5594           else
5595           {
5596             i++;
5597           }
5598           break;
5599         case FRACTION:
5600           if (ops == CONST && i == 1)
5601           {
5602             double c = (*a)->GetCoeff();
5603             a->SetTo((*a)->GetNode(0));
5604             (*a)->SetCoeff((*a)->GetCoeff() * c);
5605             ret = true;
5606             sz--;
5607           }
5608           else
5609           {
5610             i++;
5611           }
5612           if (sz >= 2 && (*a)->GetNode(0)->IsConstant() &&
5613               (*a)->GetNode(1)->IsConstant())
5614           {
5615             double d = (*a)->GetNode(1)->GetValue();
5616             if (d == 0)
5617             {
5618               throw ErrDivideByZero(23, "Expression", "SimplifyConstant",
5619                                     "d==0",
5620                                     "cannot divide by zero", HELPURL,
5621                                     (*a)->ToString());
5622             }
5623             ret = true;
5624             a->SetTo((*a)->GetNode(0));
5625             (*a)->SetValue((*a)->GetValue() / d);
5626             (*a)->SetCoeff(1.0);
5627             (*a)->SetExponent(1.0);
5628             sz = 0;
5629           }
5630           break;
5631         case POWER:
5632           if (sz >= 2 && (*a)->GetNode(0)->IsConstant() &&
5633               (*a)->GetNode(1)->IsConstant())
5634           {
5635             double d = (*a)->GetNode(1)->GetValue();
5636             ret = true;
5637             a->SetTo((*a)->GetNode(0));
5638             (*a)->SetValue(pow((*a)->GetValue(), d));
5639             (*a)->SetCoeff(1.0);
5640             (*a)->SetExponent(1.0);
5641             sz = 0;
5642           }
5643           else
5644           {
5645             i++;
5646           }
5647           break;
5648         case LOG:
5649           if ((*a)->GetNode(0)->IsConstant())
5650           {
5651             double d = (*a)->GetNode(0)->GetValue();
5652             if (d <= 0)
5653             {
5654               throw ErrNotPermitted(24, "Expression", "SimplifyConstant",
5655                                     "d<=0",
5656                                     "log of nonpositive not allowed", HELPURL);
5657             }
5658             ret = true;
5659             a->SetTo((*a)->GetNode(0));
5660             (*a)->SetValue(log(d));
5661             (*a)->SetCoeff(1.0);
5662             (*a)->SetExponent(1.0);
5663             sz = 0;
5664           }
5665           else
5666           {
5667             i++;
5668           }
5669           break;
5670         case EXP:
5671           if ((*a)->GetNode(0)->IsConstant())
5672           {
5673             double d = (*a)->GetNode(0)->GetValue();
5674             ret = true;
5675             a->SetTo((*a)->GetNode(0));
5676             (*a)->SetValue(exp(d));
5677             (*a)->SetCoeff(1.0);
5678             (*a)->SetExponent(1.0);
5679             sz = 0;
5680           }
5681           else
5682           {
5683             i++;
5684           }
5685           break;
5686         case SIN:
5687           if ((*a)->GetNode(0)->IsConstant())
5688           {
5689             double d = (*a)->GetNode(0)->GetValue();
5690             ret = true;
5691             a->SetTo((*a)->GetNode(0));
5692             (*a)->SetValue(sin(d));
5693             (*a)->SetCoeff(1.0);
5694             (*a)->SetExponent(1.0);
5695             sz = 0;
5696           }
5697           else
5698           {
5699             i++;
5700           }
5701           break;
5702         case COS:
5703           if ((*a)->GetNode(0)->IsConstant())
5704           {
5705             double d = (*a)->GetNode(0)->GetValue();
5706             ret = true;
5707             a->SetTo((*a)->GetNode(0));
5708             (*a)->SetValue(cos(d));
5709             (*a)->SetCoeff(1.0);
5710             (*a)->SetExponent(1.0);
5711             sz = 0;
5712           }
5713           else
5714           {
5715             i++;
5716           }
5717           break;
5718         case TAN:
5719           if ((*a)->GetNode(0)->IsConstant())
5720           {
5721             double d = (*a)->GetNode(0)->GetValue();
5722             ret = true;
5723             a->SetTo((*a)->GetNode(0));
5724             (*a)->SetValue(tan(d));
5725             (*a)->SetCoeff(1.0);
5726             (*a)->SetExponent(1.0);
5727             sz = 0;
5728           }
5729           else
5730           {
5731             i++;
5732           }
5733           break;
5734         case COT:
5735           if ((*a)->GetNode(0)->IsConstant())
5736           {
5737             double d = (*a)->GetNode(0)->GetValue();
5738             ret = true;
5739             a->SetTo((*a)->GetNode(0));
5740             (*a)->SetValue(1 / tan(d));
5741             (*a)->SetCoeff(1.0);
5742             (*a)->SetExponent(1.0);
5743             sz = 0;
5744           }
5745           else
5746           {
5747             i++;
5748           }
5749           break;
5750         case SINH:
5751           if ((*a)->GetNode(0)->IsConstant())
5752           {
5753             double d = (*a)->GetNode(0)->GetValue();
5754             ret = true;
5755             a->SetTo((*a)->GetNode(0));
5756             (*a)->SetValue(sinh(d));
5757             (*a)->SetCoeff(1.0);
5758             (*a)->SetExponent(1.0);
5759             sz = 0;
5760           }
5761           else
5762           {
5763             i++;
5764           }
5765           break;
5766         case COSH:
5767           if ((*a)->GetNode(0)->IsConstant())
5768           {
5769             double d = (*a)->GetNode(0)->GetValue();
5770             ret = true;
5771             a->SetTo((*a)->GetNode(0));
5772             (*a)->SetValue(cosh(d));
5773             (*a)->SetCoeff(1.0);
5774             (*a)->SetExponent(1.0);
5775             sz = 0;
5776           }
5777           else
5778           {
5779             i++;
5780           }
5781           break;
5782         case TANH:
5783           if ((*a)->GetNode(0)->IsConstant())
5784           {
5785             double d = (*a)->GetNode(0)->GetValue();
5786             ret = true;
5787             a->SetTo((*a)->GetNode(0));
5788             (*a)->SetValue(tanh(d));
5789             (*a)->SetCoeff(1.0);
5790             (*a)->SetExponent(1.0);
5791             sz = 0;
5792           }
5793           else
5794           {
5795             i++;
5796           }
5797           break;
5798         case COTH:
5799           if ((*a)->GetNode(0)->IsConstant())
5800           {
5801             double d = (*a)->GetNode(0)->GetValue();
5802             ret = true;
5803             a->SetTo((*a)->GetNode(0));
5804             (*a)->SetValue(1 / tanh(d));
5805             (*a)->SetCoeff(1.0);
5806             (*a)->SetExponent(1.0);
5807             sz = 0;
5808           }
5809           else
5810           {
5811             i++;
5812           }
5813           break;
5814         case SQRT:
5815           if ((*a)->GetNode(0)->IsConstant())
5816           {
5817             double d = (*a)->GetNode(0)->GetValue();
5818             if (d <= 0)
5819             {
5820               throw ErrNotPermitted(25, "Expression", "SimplifyConstant",
5821                                     "d<=0",
5822                                     "sqrt of nonpositive not allowed", HELPURL);
5823             }
5824             ret = true;
5825             a->SetTo((*a)->GetNode(0));
5826             (*a)->SetValue(sqrt(d));
5827             (*a)->SetCoeff(1.0);
5828             (*a)->SetExponent(1.0);
5829             sz = 0;
5830           }
5831           else
5832           {
5833             i++;
5834           }
5835           break;
5836         default:
5837           i++;
5838           break;
5839       }
5840     }
5841   }
5842   return ret;
5843 }
5844 
SimplifyRecursive(Expression * a)5845 bool SimplifyRecursive(Expression* a)
5846 {
5847   bool ret = false;
5848   bool ischanged = false;
5849   // signals whether we're dealing with
5850   // -1 : nothing
5851   // 0 : constants
5852   // 1 : linear variables
5853   // 2 : a variable raised to an exponent different from 1
5854   // 3 : any other more complex node
5855   if (!(*a)->IsLeaf())
5856   {
5857     int op = (*a)->GetOpType();
5858     Expression t1, t2;
5859     int i, j;
5860     for(i = 0; i < (*a)->GetSize(); i++)
5861     {
5862       ischanged = SimplifyRecursive((*a)->GetNodePtr(i));
5863       if (!ret && ischanged)
5864         ret = true;
5865     }
5866     int status = -1;
5867     int prestatus = -1;
5868     double consolidated[4] = {0, 0, 0, 0};
5869     double expon = 0;
5870     double preexpon = 0;
5871     double c = 0;
5872     int prevarindex = -1;
5873     int prevarpowindex = -1;
5874     int varindex = -1;
5875     int varpowindex = -1;
5876     int firstvarindex = -1;
5877     int firstvarpowindex = -1;
5878     int firstconstindex = -1;
5879     int sz = (*a)->GetSize();
5880     Expression one(1.0);
5881 
5882     switch(op)
5883     {
5884       case SUM:
5885         i = 0;
5886         while(i < sz)
5887         {
5888           // work out which status we're in
5889           if ((*a)->GetNode(i)->IsConstant())
5890           {
5891             if (status == -1 || firstconstindex == -1)
5892             {
5893               firstconstindex = i;
5894             }
5895             // constant
5896             status = 0;
5897           }
5898           else if ((*a)->GetNode(i)->IsVariable() &&
5899                    (*a)->GetNode(i)->GetExponent() == 1)
5900           {
5901             // variable
5902             status = 1;
5903           }
5904           else if ((*a)->GetNode(i)->IsVariable() &&
5905                    (*a)->GetNode(i)->GetExponent() != 1)
5906           {
5907             // variable raised to power
5908             status = 2;
5909           }
5910           else
5911           {
5912             // other term
5913             status = 3;
5914           }
5915           if (status == 0)
5916           {
5917             // constant
5918             consolidated[status] += (*a)->GetNode(i)->GetValue();
5919             (*a)->GetNode(firstconstindex)->SetValue(consolidated[status]);
5920             (*a)->GetNode(firstconstindex)->SetCoeff(1.0);
5921             (*a)->GetNode(firstconstindex)->SetExponent(1.0);
5922             if (prestatus == 0)
5923             {
5924               (*a)->DeleteNode(i);
5925               ret = true;
5926               sz--;
5927               if (sz == 1)
5928               {
5929                 a->SetTo((*a)->GetNode(0));
5930                 i = 0;
5931                 sz = (*a)->GetSize();
5932               }
5933             }
5934             else
5935             {
5936               i++;
5937             }
5938           }
5939           else if (status == 1)
5940           {
5941             // variable
5942             varindex = (*a)->GetNode(i)->GetVarIndex();
5943             c = (*a)->GetNode(i)->GetCoeff();
5944             if (varindex != prevarindex)
5945             {
5946               firstvarindex = i;
5947               consolidated[status] = c;
5948               i++;
5949             }
5950             else
5951             {
5952               consolidated[status] += c;
5953               (*a)->GetNode(firstvarindex)->SetCoeff(consolidated[status]);
5954               ret = true;
5955               (*a)->DeleteNode(i);
5956               sz--;
5957               if (sz == 1)
5958               {
5959                 a->SetTo((*a)->GetNode(0));
5960                 i = 0;
5961                 sz = (*a)->GetSize();
5962               }
5963             }
5964             prevarindex = varindex;
5965           }
5966           else if (status == 2)
5967           {
5968             // variable raised to power
5969             varpowindex = (*a)->GetNode(i)->GetVarIndex();
5970             expon = (*a)->GetNode(i)->GetExponent();
5971             c = (*a)->GetNode(i)->GetCoeff();
5972             if (expon != preexpon || varpowindex != prevarpowindex)
5973             {
5974               firstvarpowindex = i;
5975               consolidated[status] = c;
5976               i++;
5977             }
5978             else
5979             {
5980               consolidated[status] += c;
5981               (*a)->GetNode(firstvarpowindex)->SetCoeff(consolidated[status]);
5982               ret = true;
5983               (*a)->DeleteNode(i);
5984               sz--;
5985               if (sz == 1)
5986               {
5987                 a->SetTo((*a)->GetNode(0));
5988                 i = 0;
5989                 sz = (*a)->GetSize();
5990               }
5991             }
5992             preexpon = expon;
5993             prevarpowindex = varpowindex;
5994           }
5995           else if (status == 3)
5996           {
5997             // other term
5998             c = (*a)->GetNode(i)->GetCoeff();
5999             firstvarindex = i;
6000             consolidated[status] = c;
6001             j = i + 1;
6002             while(j < sz)
6003             {
6004               if ((*a)->GetNode(i)->IsEqualToNoCoeff((*a)->GetNode(j)))
6005               {
6006                 c = (*a)->GetNode(j)->GetCoeff();
6007                 consolidated[status] += c;
6008                 ret = true;
6009                 (*a)->GetNode(firstvarindex)->SetCoeff(consolidated[status]);
6010                 RecursiveDestroy((*a)->GetNodePtr(j));
6011                 (*a)->DeleteNode(j);
6012                 sz--;
6013                 if (sz == 1)
6014                 {
6015                   a->SetTo((*a)->GetNode(0));
6016                   j = i + 1;
6017                   sz = (*a)->GetSize();
6018                 }
6019               }
6020               else
6021               {
6022                 j++;
6023               }
6024             }
6025             i++;
6026           }
6027           else
6028           {
6029             // should never happen, but anyway...
6030             i++;
6031           }
6032           // update status of last iteration
6033           prestatus = status;
6034         }
6035         break;
6036       case PRODUCT:
6037         i = 0;
6038         prevarindex = -1;
6039         consolidated[0] = 1;
6040         expon = 0;
6041         while(i < sz)
6042         {
6043           if ((*a)->GetNode(i)->IsVariable())
6044           {
6045             varindex = (*a)->GetNode(i)->GetVarIndex();
6046             if (varindex != prevarindex)
6047             {
6048               firstvarindex = i;
6049               consolidated[0] = (*a)->GetNode(i)->GetCoeff();
6050               expon = (*a)->GetNode(i)->GetExponent();
6051               i++;
6052             }
6053             else
6054             {
6055               consolidated[0] *= (*a)->GetNode(i)->GetCoeff();
6056               expon += (*a)->GetNode(i)->GetExponent();
6057               (*a)->GetNode(firstvarindex)->SetCoeff(consolidated[0]);
6058               (*a)->GetNode(firstvarindex)->SetExponent(expon);
6059               (*a)->DeleteNode(i);
6060               ret = true;
6061               sz--;
6062               if (sz == 1)
6063               {
6064                 a->SetTo((*a)->GetNode(0));
6065                 i = 0;
6066                 sz = (*a)->GetSize();
6067               }
6068             }
6069           }
6070           else if (!(*a)->GetNode(i)->IsLeaf())
6071           {
6072             // WARNING: work to be done
6073             // not going to do the same as in sum just yet, maybe future
6074             // work - transform expr * expr in expr^2 when expr not a variable
6075             i++;
6076           }
6077         }
6078         break;
6079       case FRACTION:
6080         if ((*a)->GetNode(0)->IsEqualTo((*a)->GetNode(1)))
6081         {
6082           // f(x)/f(x)
6083           c = (*a)->GetCoeff();
6084           RecursiveDestroy(a);
6085           a->SetTo(Expression(c));
6086           ret = true;
6087           sz = 0;
6088         }
6089         else
6090         {
6091           // try to simplify denominator by one of numerator factors
6092           if ((*a)->GetNode(0)->GetOpType() == PRODUCT)
6093           {
6094             for(j = 0; j < (*a)->GetNode(0)->GetSize(); j++)
6095             {
6096               if ((*a)->GetNode(1)->IsEqualTo((*a)->GetNode(0)->GetNode(j)))
6097               {
6098                 c = (*a)->GetCoeff();
6099                 a->SetTo((*a)->GetNode(0));
6100                 (*a)->SetCoeff((*a)->GetCoeff() * c);
6101                 (*a)->DeleteNode(j);
6102                 ret = true;
6103                 sz = 0;
6104                 break;
6105               }
6106             }
6107           }
6108           // do the opposite
6109           if (sz > 0 && (*a)->GetNode(1)->GetOpType() == PRODUCT)
6110           {
6111             for(j = 0; j < (*a)->GetNode(1)->GetSize(); j++)
6112             {
6113               if ((*a)->GetNode(0)->IsEqualTo((*a)->GetNode(1)->GetNode(j)))
6114               {
6115                 *((*a)->GetNodePtr(0)) = Pointer<BasicExpression>(one);
6116                 (*a)->GetNode(1)->DeleteNode(j);
6117                 ret = true;
6118                 sz = 0;
6119                 break;
6120               }
6121             }
6122           }
6123           if (sz > 0 && (*a)->GetNode(0)->GetOpType() == PRODUCT &&
6124               (*a)->GetNode(1)->GetOpType() == PRODUCT)
6125           {
6126             // both num and denom. are products, try and find common factors
6127             int k = 0;
6128             int sz1, sz2;
6129             j = 0;
6130             sz1 = (*a)->GetNode(0)->GetSize();
6131             sz2 = (*a)->GetNode(1)->GetSize();
6132             while (j < sz1)
6133             {
6134               k = 0;
6135               while (k < sz2)
6136               {
6137                 if ((*a)->GetNode(0)->GetNode(j)->IsEqualTo
6138                     ((*a)->GetNode(1)->GetNode(k)))
6139                 {
6140                   (*a)->GetNode(0)->DeleteNode(j);
6141                   (*a)->GetNode(1)->DeleteNode(k);
6142                   ret = true;
6143                   sz1--;
6144                   if (sz1 == 0)
6145                   {
6146                     // numerator empty, replace with 1
6147                     (*a)->GetNode(0)->One();
6148                   }
6149                   sz2--;
6150                   if (sz2 == 0)
6151                   {
6152                     // denominator empty, node becomes num.
6153                     a->SetTo((*a)->GetNode(0));
6154                   }
6155                   if (sz1 == 0 && sz2 == 0)
6156                   {
6157                     // 1/1, simplify
6158                     (*a)->One();
6159                   }
6160                   if (sz1 == 0 || sz2 == 0)
6161                   {
6162                     // either num. or den. 1, exit loop
6163                     sz1 = 0;
6164                     sz2 = 0;
6165                     break;
6166                   }
6167                   j--;
6168                 }
6169                 else
6170                 {
6171                   k++;
6172                 }
6173               }
6174               j++;
6175             }
6176           }
6177         }
6178         sz = 0;
6179         break;
6180       case POWER:
6181         if (sz == 2 &&
6182             (*a)->GetNode(0)->IsVariable() &&
6183             (*a)->GetNode(1)->IsConstant())
6184         {
6185           // case var^const, transform in variable with an exponent
6186           expon = (*a)->GetNode(1)->GetValue();
6187           c = (*a)->GetCoeff();
6188           double c0 = (*a)->GetNode(0)->GetCoeff();
6189           (*a)->GetNode(0)->SetExponent(expon);
6190           (*a)->DeleteNode(1);
6191           a->SetTo((*a)->GetNode(0));
6192           (*a)->SetCoeff(c * pow(c0, expon));
6193         }
6194         break;
6195       default:
6196         break;
6197     }
6198   }
6199   return ret;
6200 }
6201 
DifferenceToSum(Expression * a)6202 bool DifferenceToSum(Expression* a)
6203 {
6204   bool ret = false;
6205   double d = 0., e = 0.;
6206   if (!(*a)->IsLeaf())
6207   {
6208     if (((*a)->GetOpType() == SUM || (*a)->GetOpType() == DIFFERENCE) &&
6209         (*a)->GetSize() == 1)
6210     {
6211       DifferenceToSum((*a)->GetNodePtr(0));
6212       // replace a with its child
6213       a->SetTo((*a)->GetNode(0));
6214       ret = true;
6215     }
6216     if ((*a)->GetOpType() == DIFFERENCE)
6217     {
6218       int i;
6219       (*a)->SetOpType(SUM);
6220       for(i = 1; i < (*a)->GetSize(); i++)
6221       {
6222         // start from node 1 not 0 because a difference is +op0 -op1 -op2 ...
6223         (*a)->GetNode(i)->SetCoeff(- (*a)->GetNode(i)->GetCoeff());
6224       }
6225     }
6226     else if ((*a)->GetOpType() == MINUS)
6227     {
6228       d = (*a)->GetCoeff();
6229       e = (*a)->GetExponent();
6230       if (is_even(e))
6231       {
6232         // replace a with its child and adjust coeff
6233         a->SetTo((*a)->GetNode(0));
6234         (*a)->SetCoeff((*a)->GetCoeff() * d); // since exponent is even, +
6235         (*a)->SetExponent((*a)->GetExponent() * e);
6236         ret = true;
6237       }
6238       else if (is_odd(e))
6239       {
6240         // replace a with its child and adjust coeff
6241         a->SetTo((*a)->GetNode(0));
6242         (*a)->SetCoeff(- (*a)->GetCoeff() * d); // since exponent is odd, -
6243         (*a)->SetExponent((*a)->GetExponent() * e);
6244         ret = true;
6245       }
6246     }
6247     else if ((*a)->GetOpType() == PLUS)
6248     {
6249       // replace a with its child
6250       a->SetTo((*a)->GetNode(0));
6251       (*a)->SetCoeff((*a)->GetCoeff() * d); // since exponent is even, +
6252       (*a)->SetExponent((*a)->GetExponent() * e);
6253       ret = true;
6254     }
6255   }
6256   return ret;
6257 }
6258 
6259 // standard order for a set of subnodes of a sum is:
6260 // constants + linear variables + vars^{rising powers} + complex operands
6261 class NodeOrderSum
6262 {
6263 public:
operator ()(const Expression & a,const Expression & b)6264   int operator() (const Expression& a,
6265                   const Expression& b)
6266   {
6267     if (a->IsConstant() && !b->IsConstant())
6268     {
6269       return true;
6270     }
6271     else if (a->IsVariable() && b->IsVariable())
6272     {
6273       if (a->GetExponent() == 1 && b->GetExponent() != 1)
6274       {
6275         return true;
6276       }
6277       else if (a->GetExponent() < b->GetExponent())
6278       {
6279         return true;
6280       }
6281       else if (a->GetExponent() > b->GetExponent())
6282       {
6283         return false;
6284       }
6285       else
6286       {
6287         if (a->GetVarIndex() < b->GetVarIndex())
6288         {
6289           return true;
6290         }
6291         else
6292         {
6293           return false;
6294         }
6295       }
6296     }
6297     else if (a->IsLeaf() && !b->IsLeaf())
6298     {
6299       return true;
6300     }
6301     else
6302     {
6303       return false;
6304     }
6305   }
6306 };
6307 
6308 // standard order for a set of subnodes is:
6309 // constants + vars^{rising powers} + complex operands
6310 class NodeOrder
6311 {
6312 public:
operator ()(const Expression & a,const Expression & b)6313   int operator() (const Expression& a,
6314                   const Expression& b)
6315   {
6316     if (a->IsConstant() && !b->IsConstant())
6317     {
6318       return true;
6319     }
6320     else if (a->IsVariable() && b->IsVariable())
6321     {
6322       if (a->GetExponent() < b->GetExponent())
6323       {
6324         return true;
6325       }
6326       else if (a->GetExponent() > b->GetExponent())
6327       {
6328         return false;
6329       }
6330       else
6331       {
6332         if (a->GetVarIndex() < b->GetVarIndex())
6333         {
6334           return true;
6335         }
6336         else
6337         {
6338           return false;
6339         }
6340       }
6341     }
6342     else if (a->IsLeaf() && !b->IsLeaf())
6343     {
6344       return true;
6345     }
6346     else
6347     {
6348       return false;
6349     }
6350   }
6351 };
6352 
ReorderNodes(Expression * a)6353 bool ReorderNodes(Expression* a)
6354 {
6355   bool ret = false;
6356   if (!(*a)->IsLeaf() && (*a)->GetSize() > 1 &&
6357       ((*a)->GetOpType() == SUM || (*a)->GetOpType() == PRODUCT))
6358   {
6359     int i;
6360     for(i = 0; i < (*a)->GetSize(); i++)
6361     {
6362       ReorderNodes((*a)->GetNodePtr(i));
6363     }
6364     // how do I get this sort to tell me whether it did anything or not?
6365     // at the moment this function returns false by definition, incorrect
6366     if ((*a)->GetOpType() == SUM)
6367     {
6368       sort(((*a)->GetNodeVectorPtr())->begin(),
6369            ((*a)->GetNodeVectorPtr())->end(), NodeOrderSum());
6370     }
6371     else
6372     {
6373       sort(((*a)->GetNodeVectorPtr())->begin(),
6374            ((*a)->GetNodeVectorPtr())->end(), NodeOrder());
6375     }
6376   }
6377   return ret;
6378 }
6379 
CompactLinearPart(Expression * a)6380 bool CompactLinearPart(Expression* a)
6381 {
6382   bool ret = false;
6383   bool ischanged = false;
6384   ischanged = SimplifyConstant(a);
6385   if (!ret && ischanged)
6386     ret = true;
6387   ischanged = DifferenceToSum(a);
6388   if (!ret && ischanged)
6389     ret = true;
6390   ischanged = CompactLinearPartRecursive(a);
6391   if (!ret && ischanged)
6392     ret = true;
6393   ischanged = ReorderNodes(a);
6394   return ret;
6395 }
6396 
CompactLinearPartRecursive(Expression * a)6397 bool CompactLinearPartRecursive(Expression* a)
6398 {
6399   bool ret = false;
6400   bool ischanged = false;
6401   int i, j;
6402   i = 0;
6403   int sz = (*a)->GetSize();
6404   if ((*a)->GetOpType() == SUM)
6405   {
6406     while(i < sz)
6407     {
6408       ischanged = CompactLinearPartRecursive((*a)->GetNodePtr(i));
6409       if (!ret && ischanged)
6410         ret = true;
6411       if ((*a)->GetNode(i)->GetOpType() == SUM)
6412       {
6413         ret = true;
6414         double ci = (*a)->GetNode(i)->GetCoeff();
6415         for(j = 0; j < (*a)->GetNode(i)->GetSize(); j++)
6416         {
6417           Expression nodej((*a)->GetNode(i)->GetNode(j));
6418           nodej->SetCoeff(nodej->GetCoeff() * ci);
6419           (*a)->AddNode(nodej);
6420           ++ sz;// we added a node
6421         }
6422         (*a)->DeleteNode(i);
6423         -- sz; // we have deleted a node
6424         // we don't need to increase i, since we have deleted the i-th node
6425         // the next node is still the i-th node
6426         if (sz == 1)
6427         {
6428           a->SetTo((*a)->GetNode(0));
6429           i = 0;
6430           sz = (*a)->GetSize();
6431         }
6432       }
6433       else
6434       {
6435         i++;
6436       }
6437     }
6438   }
6439   return ret;
6440 }
6441 
6442 
6443 // deals with cases like *(*(x,y), z) --> *(x,y,z)
CompactProducts(Expression * a)6444 bool CompactProducts(Expression* a)
6445 {
6446   bool ret = false;
6447   bool ischanged = false;
6448   int i, j;
6449   if ((*a)->GetOpType() == PRODUCT)
6450   {
6451     for(i = 0; i < (*a)->GetSize(); i++)
6452     {
6453       ischanged = CompactProducts((*a)->GetNodePtr(i));
6454       if (!ret && ischanged)
6455         ret = true;
6456       if ((*a)->GetNode(i)->GetOpType() == PRODUCT)
6457       {
6458         ret = true;
6459         for(j = 0; j < (*a)->GetNode(i)->GetSize(); j++)
6460         {
6461           (*a)->AddNode((*a)->GetNode(i)->GetNode(j));
6462         }
6463         (*a)->DeleteNode(i);
6464       }
6465     }
6466     if ((*a)->GetSize() == 1)
6467     {
6468       // product with just one operand, up a level
6469       double c = (*a)->GetCoeff();
6470       a->SetTo((*a)->GetNode(0));
6471       (*a)->SetCoeff((*a)->GetCoeff() * c);
6472       ret = true;
6473     }
6474   }
6475   else
6476   {
6477     // not a product, recurse
6478     for(i = 0; i < (*a)->GetSize(); i++)
6479     {
6480       ischanged = CompactProducts((*a)->GetNodePtr(i));
6481       if (!ret && ischanged)
6482       {
6483         ret = true;
6484       }
6485     }
6486   }
6487   (*a)->ConsolidateProductCoeffs();
6488   return ret;
6489 }
6490 
6491 // generic simplification on a copy of the expression
SimplifyCopy(Expression * a,bool & ischanged)6492 Expression SimplifyCopy(Expression* a,
6493                         bool & ischanged)
6494 {
6495   Expression b;
6496   b = (*a).Copy();
6497   ischanged = Simplify(&b);
6498   return b;
6499 }
6500 
6501 // recursive destroy - deleted all the tree and nodes in a tree - use
6502 // with caution
RecursiveDestroy(Expression * a)6503 void RecursiveDestroy(Expression* a)
6504 {
6505   int i;
6506   for(i = 0; i < (*a)->GetSize(); i++)
6507   {
6508     RecursiveDestroy((*a)->GetNodePtr(i));
6509   }
6510   a->Destroy();
6511 }
6512 
6513 
6514 } /* namespace Ev3 */
6515