b311480e |
1 | // Created on: 1991-04-17 |
2 | // Created by: Arnaud BOUZY |
3 | // Copyright (c) 1991-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
8 | // This library is free software; you can redistribute it and/or modify it under |
9 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
10 | // by the Free Software Foundation, with special exception defined in the file |
11 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
12 | // distribution for complete text of the license and disclaimer of any warranty. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
0797d9d3 |
17 | #ifndef OCCT_DEBUG |
7fd59977 |
18 | #define No_Standard_RangeError |
19 | #define No_Standard_OutOfRange |
20 | #endif |
21 | |
42cf5bc1 |
22 | |
7fd59977 |
23 | #include <Expr.hxx> |
42cf5bc1 |
24 | #include <Expr_GeneralExpression.hxx> |
ec357c5c |
25 | #include <Expr_NamedUnknown.hxx> |
42cf5bc1 |
26 | #include <Expr_NotEvaluable.hxx> |
27 | #include <Expr_NumericValue.hxx> |
28 | #include <Expr_Operators.hxx> |
29 | #include <Expr_Product.hxx> |
30 | #include <Expr_Sum.hxx> |
31 | #include <Expr_UnaryMinus.hxx> |
32 | #include <Standard_NumericError.hxx> |
33 | #include <Standard_Type.hxx> |
34 | #include <TCollection_AsciiString.hxx> |
35 | #include <TColStd_Array1OfInteger.hxx> |
7fd59977 |
36 | |
92efcf78 |
37 | IMPLEMENT_STANDARD_RTTIEXT(Expr_Product,Expr_PolyExpression) |
38 | |
7fd59977 |
39 | Expr_Product::Expr_Product (const Expr_SequenceOfGeneralExpression& exps) |
40 | { |
41 | Standard_Integer i; |
42 | Standard_Integer max = exps.Length(); |
43 | for (i=1; i<= max; i++) { |
44 | AddOperand(exps(i)); |
45 | } |
46 | } |
47 | |
48 | Expr_Product::Expr_Product (const Handle(Expr_GeneralExpression)& exp1, const Handle(Expr_GeneralExpression)& exp2) |
49 | { |
50 | AddOperand(exp1); |
51 | AddOperand(exp2); |
52 | } |
53 | |
54 | Handle(Expr_GeneralExpression) Expr_Product::Copy () const |
55 | { |
56 | Standard_Integer i; |
57 | Standard_Integer max = NbOperands(); |
58 | Expr_SequenceOfGeneralExpression simps; |
59 | for (i=1; i<= max; i++) { |
60 | simps.Append(Expr::CopyShare(Operand(i))); |
61 | } |
62 | return new Expr_Product(simps); |
63 | } |
64 | |
65 | Standard_Boolean Expr_Product::IsIdentical (const Handle(Expr_GeneralExpression)& Other) const |
66 | { |
67 | if (!Other->IsKind(STANDARD_TYPE(Expr_Product))) { |
68 | return Standard_False; |
69 | } |
70 | Handle(Expr_Product) me = this; |
71 | Handle(Expr_Product) POther = Handle(Expr_Product)::DownCast(Other); |
72 | Standard_Integer max = NbOperands(); |
73 | if (POther->NbOperands() != max) { |
74 | return Standard_False; |
75 | } |
76 | Handle(Expr_GeneralExpression) myop; |
77 | Handle(Expr_GeneralExpression) hisop; |
78 | Standard_Integer i=1; |
79 | TColStd_Array1OfInteger tab(1,max); |
80 | for (Standard_Integer k=1; k<=max;k++) { |
81 | tab(k)=0; |
82 | } |
83 | Standard_Boolean ident = Standard_True; |
84 | while ((i<=max) && (ident)) { |
85 | Standard_Integer j=1; |
86 | Standard_Boolean found = Standard_False; |
87 | myop = Operand(i); |
88 | while ((j<=max) && (!found)) { |
89 | hisop = POther->Operand(j); |
90 | found = myop->IsIdentical(hisop); |
91 | if (found) { |
92 | found = (tab(j) == 0); |
93 | tab(j)=i; |
94 | } |
95 | j++; |
96 | } |
97 | ident = found; |
98 | i++; |
99 | } |
100 | return ident; |
101 | } |
102 | |
103 | Standard_Boolean Expr_Product::IsLinear () const |
104 | { |
105 | Standard_Integer i; |
106 | Standard_Integer max = NbOperands(); |
107 | Standard_Boolean lin = Standard_True; |
108 | Standard_Boolean res = Standard_True; |
109 | Handle(Expr_GeneralExpression) asimp; |
110 | for (i=1; (i <= max) && res ; i++) { |
111 | asimp = Operand(i); |
112 | if (asimp->IsKind(STANDARD_TYPE(Expr_NamedUnknown)) || asimp->ContainsUnknowns()) { |
113 | if (lin) { |
114 | lin = Standard_False; |
115 | if (!asimp->IsLinear()) { |
116 | res = Standard_False; |
117 | } |
118 | } |
119 | else { |
120 | res = Standard_False; |
121 | } |
122 | } |
123 | } |
124 | return res; |
125 | } |
126 | |
127 | Handle(Expr_GeneralExpression) Expr_Product::Derivative (const Handle(Expr_NamedUnknown)& X) const |
128 | { |
129 | if (!Contains(X)) { |
130 | return new Expr_NumericValue(0.0); |
131 | } |
132 | Handle(Expr_GeneralExpression) firstop = Expr::CopyShare(Operand(1)); // U |
133 | Handle(Expr_GeneralExpression) tailop; // V |
134 | Standard_Integer nbop = NbOperands(); |
135 | if (nbop == 2) { |
136 | tailop = Expr::CopyShare(Operand(2)); |
137 | } |
138 | else { |
139 | Handle(Expr_Product) prodop = Expr::CopyShare(Operand(2))*Expr::CopyShare(Operand(3)); |
140 | for (Standard_Integer i=4; i<= nbop; i++) { |
141 | prodop->AddOperand(Expr::CopyShare(Operand(i))); |
142 | } |
143 | tailop = prodop; |
144 | } |
145 | Handle(Expr_GeneralExpression) firstder = firstop->Derivative(X); // U' |
146 | Handle(Expr_GeneralExpression) tailder = tailop->Derivative(X); // V' |
147 | |
148 | Handle(Expr_Product) firstmember = firstop * tailder; // U*V' |
149 | |
150 | Handle(Expr_Product) secondmember = firstder * tailop; // U'*V |
151 | |
152 | Handle(Expr_Sum) resu = firstmember->ShallowSimplified() + secondmember->ShallowSimplified(); |
153 | // U*V' + U'*V |
154 | |
155 | return resu->ShallowSimplified(); |
156 | } |
157 | |
158 | |
159 | Handle(Expr_GeneralExpression) Expr_Product::ShallowSimplified () const |
160 | { |
161 | Standard_Integer i; |
162 | Standard_Integer max = NbOperands(); |
163 | Handle(Expr_GeneralExpression) op; |
164 | Expr_SequenceOfGeneralExpression newops; |
7fd59977 |
165 | Standard_Real vals = 0.; |
7fd59977 |
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 | } |