18655066aa282eb8d5f718875c3e4f06f9e1c873
[occt.git] / src / Expr / Expr_Product.cxx
1 // Created on: 1991-04-17
2 // Created by: Arnaud BOUZY
3 // Copyright (c) 1991-1999 Matra Datavision
4 // Copyright (c) 1999-2012 OPEN CASCADE SAS
5 //
6 // The content of this file is subject to the Open CASCADE Technology Public
7 // License Version 6.5 (the "License"). You may not use the content of this file
8 // except in compliance with the License. Please obtain a copy of the License
9 // at http://www.opencascade.org and read it completely before using this file.
10 //
11 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
12 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
13 //
14 // The Original Code and all software distributed under the License is
15 // distributed on an "AS IS" basis, without warranty of any kind, and the
16 // Initial Developer hereby disclaims all such warranties, including without
17 // limitation, any warranties of merchantability, fitness for a particular
18 // purpose or non-infringement. Please see the License for the specific terms
19 // and conditions governing the rights and limitations under the License.
20
21
22 #ifndef DEB
23 #define No_Standard_RangeError
24 #define No_Standard_OutOfRange
25 #endif
26
27 #include <Expr_Product.ixx>
28 #include <TColStd_Array1OfInteger.hxx>
29 #include <Expr_Sum.hxx>
30 #include <Expr_UnaryMinus.hxx>
31 #include <Expr_NumericValue.hxx>
32 #include <Expr_Operators.hxx>
33 #include <Expr.hxx>
34
35 Expr_Product::Expr_Product (const Expr_SequenceOfGeneralExpression& exps)
36 {
37   Standard_Integer i;
38   Standard_Integer max = exps.Length();
39   for (i=1; i<= max; i++) {
40     AddOperand(exps(i));
41   }
42 }
43
44 Expr_Product::Expr_Product (const Handle(Expr_GeneralExpression)& exp1, const Handle(Expr_GeneralExpression)& exp2)
45 {
46   AddOperand(exp1);
47   AddOperand(exp2);
48 }
49
50 Handle(Expr_GeneralExpression) Expr_Product::Copy () const
51 {
52   Standard_Integer i;
53   Standard_Integer max = NbOperands();
54   Expr_SequenceOfGeneralExpression simps;
55   for (i=1; i<= max; i++) {
56     simps.Append(Expr::CopyShare(Operand(i)));
57   }
58   return new Expr_Product(simps);
59 }
60
61 Standard_Boolean Expr_Product::IsIdentical (const Handle(Expr_GeneralExpression)& Other) const
62 {
63   if (!Other->IsKind(STANDARD_TYPE(Expr_Product))) {
64     return Standard_False;
65   }
66   Handle(Expr_Product) me = this;
67   Handle(Expr_Product) POther = Handle(Expr_Product)::DownCast(Other);
68   Standard_Integer max = NbOperands();
69   if (POther->NbOperands() != max) {
70     return Standard_False;
71   }
72   Handle(Expr_GeneralExpression) myop;
73   Handle(Expr_GeneralExpression) hisop;
74   Standard_Integer i=1;
75   TColStd_Array1OfInteger tab(1,max);
76   for (Standard_Integer k=1; k<=max;k++) {
77     tab(k)=0;
78   }
79   Standard_Boolean ident = Standard_True;
80   while ((i<=max) && (ident)) {
81     Standard_Integer j=1;
82     Standard_Boolean found = Standard_False;
83     myop = Operand(i);
84     while ((j<=max) && (!found)) {
85       hisop = POther->Operand(j);
86       found = myop->IsIdentical(hisop);
87       if (found) {
88         found = (tab(j) == 0);
89         tab(j)=i;
90       }
91       j++;
92     }
93     ident = found;
94     i++;
95   }
96   return ident;
97 }
98
99 Standard_Boolean Expr_Product::IsLinear () const
100 {
101   Standard_Integer i;
102   Standard_Integer max = NbOperands();
103   Standard_Boolean lin = Standard_True;
104   Standard_Boolean res = Standard_True;
105   Handle(Expr_GeneralExpression) asimp;
106   for (i=1; (i <= max) && res ; i++) {
107     asimp = Operand(i);
108     if (asimp->IsKind(STANDARD_TYPE(Expr_NamedUnknown)) || asimp->ContainsUnknowns()) {
109       if (lin) {
110         lin = Standard_False;
111         if (!asimp->IsLinear()) {
112           res = Standard_False;
113         }
114       }
115       else {
116         res = Standard_False;
117       }
118     }
119   }
120   return res;
121 }
122
123 Handle(Expr_GeneralExpression) Expr_Product::Derivative (const Handle(Expr_NamedUnknown)& X) const
124 {
125   if (!Contains(X)) {
126     return new Expr_NumericValue(0.0);
127   }
128   Handle(Expr_GeneralExpression) firstop = Expr::CopyShare(Operand(1)); // U
129   Handle(Expr_GeneralExpression) tailop;                               // V
130   Standard_Integer nbop = NbOperands();
131   if (nbop == 2) {
132     tailop = Expr::CopyShare(Operand(2));
133   }
134   else {
135     Handle(Expr_Product) prodop = Expr::CopyShare(Operand(2))*Expr::CopyShare(Operand(3));
136     for (Standard_Integer i=4; i<= nbop; i++) {
137       prodop->AddOperand(Expr::CopyShare(Operand(i)));
138     }
139     tailop = prodop;
140   }
141   Handle(Expr_GeneralExpression) firstder = firstop->Derivative(X); // U'
142   Handle(Expr_GeneralExpression) tailder = tailop->Derivative(X);   // V'
143
144   Handle(Expr_Product) firstmember = firstop * tailder; // U*V'
145
146   Handle(Expr_Product) secondmember = firstder * tailop; // U'*V
147
148   Handle(Expr_Sum) resu = firstmember->ShallowSimplified() + secondmember->ShallowSimplified();
149   // U*V' + U'*V
150
151   return resu->ShallowSimplified();
152 }  
153
154
155 Handle(Expr_GeneralExpression) Expr_Product::ShallowSimplified () const
156 {
157   Standard_Integer i;
158   Standard_Integer max = NbOperands();
159   Handle(Expr_GeneralExpression) op;
160   Expr_SequenceOfGeneralExpression newops;
161 #ifndef DEB
162   Standard_Real vals = 0.;
163 #else
164   Standard_Real vals;
165 #endif
166   Standard_Integer nbvals = 0;
167   Standard_Boolean subprod = Standard_False;
168   for (i=1; (i<= max) && !subprod; i++) {
169     op = Operand(i);
170     subprod = op->IsKind(STANDARD_TYPE(Expr_Product));
171   }
172   if (subprod) {
173     Handle(Expr_GeneralExpression) other;
174     Handle(Expr_Product) prodop;
175     Standard_Integer nbsprodop;
176     for (i=1; i<= max; i++) {
177       op = Operand(i);
178       if (op->IsKind(STANDARD_TYPE(Expr_Product))) {
179         prodop = Handle(Expr_Product)::DownCast(op);
180         nbsprodop = prodop->NbOperands();
181         for (Standard_Integer j=1; j<= nbsprodop; j++) {
182           other = prodop->Operand(j);
183           newops.Append(other);
184         }
185       }
186       else {
187         newops.Append(op);
188       }
189     }
190     prodop = new Expr_Product(newops);
191     return prodop->ShallowSimplified();
192   }
193
194   Standard_Boolean noone = Standard_True;
195   for (i = 1; i <= max ; i++) {
196     op = Operand(i);
197     if (op->IsKind(STANDARD_TYPE(Expr_NumericValue))) {
198       // numeric operands are cumulated separetly
199       Handle(Expr_NumericValue) NVop = Handle(Expr_NumericValue)::DownCast(op);
200       if (nbvals == 0) {
201         noone = Standard_False;
202         vals = NVop->GetValue();
203         nbvals =1;
204       }
205       else {
206         nbvals++;
207         vals = vals * NVop->GetValue();
208       }
209     }
210     else {
211       newops.Append(op);
212     }
213   }
214   if (!noone) {
215     // numeric operands encountered
216     if (newops.IsEmpty()) {         // result is only numericvalue (even zero)
217       // only numerics
218       return new Expr_NumericValue(vals); 
219     }
220     if (vals != 0.0) {
221       if (vals == 1.0) {
222         if (newops.Length() == 1) {
223           return newops(1);
224         }
225         return new Expr_Product(newops);
226       }
227       if (vals == -1.0) {
228         Handle(Expr_GeneralExpression) thefact;
229         if (newops.Length() == 1) {
230           thefact = newops(1);
231         }
232         else {
233           thefact = new Expr_Product(newops);
234         }
235         return -(thefact);
236       }
237       if (nbvals == 1) {
238         Handle(Expr_Product) me = this;
239         return me;
240       }
241       Handle(Expr_NumericValue) thevals = new Expr_NumericValue(vals);
242       newops.Append(thevals);  // non-zero value added
243       return  new Expr_Product(newops);
244     }
245     else {
246       return new Expr_NumericValue(vals); // zero absorb
247     }
248   }
249   Handle(Expr_Product) me = this;
250   return me;
251 }
252
253 Standard_Real Expr_Product::Evaluate(const Expr_Array1OfNamedUnknown& vars, const TColStd_Array1OfReal& vals) const
254 {
255   Standard_Integer max = NbOperands();
256   Standard_Real res = 1.0;
257   for (Standard_Integer i=1;i<=max;i++) {
258     res = res * Operand(i)->Evaluate(vars,vals);
259   }
260   return res;
261 }
262
263 TCollection_AsciiString Expr_Product::String() const
264 {
265   Handle(Expr_GeneralExpression) op;
266   Standard_Integer nbop = NbOperands();
267   op = Operand(1);
268   TCollection_AsciiString str;
269   if (op->NbSubExpressions() > 1) {
270     str = "(";
271     str += op->String();
272     str += ")";
273   }
274   else {
275     str = op->String();
276   }
277   for (Standard_Integer i=2; i<=nbop; i++) {
278     str += "*";
279     op = Operand(i);
280     if (op->NbSubExpressions() > 1) {
281       str += "(";
282       str += op->String();
283       str += ")";
284     }
285     else {
286       str += op->String();
287     }
288   }
289   return str;
290 }