0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / Expr / Expr_Product.cxx
CommitLineData
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 37IMPLEMENT_STANDARD_RTTIEXT(Expr_Product,Expr_PolyExpression)
38
7fd59977 39Expr_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
48Expr_Product::Expr_Product (const Handle(Expr_GeneralExpression)& exp1, const Handle(Expr_GeneralExpression)& exp2)
49{
50 AddOperand(exp1);
51 AddOperand(exp2);
52}
53
54Handle(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
65Standard_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
103Standard_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
127Handle(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
159Handle(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
253Standard_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
263TCollection_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}