Salome HOME
Merge from V6_main_20120808 08Aug12
[modules/med.git] / src / INTERP_KERNEL / ExprEval / InterpKernelValue.cxx
1 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "InterpKernelValue.hxx"
21 #include "InterpKernelFunction.hxx"
22
23 #include <cmath>
24 #include <limits>
25 #include <algorithm>
26
27 using namespace INTERP_KERNEL;
28
29 ValueDouble::ValueDouble():_data(std::numeric_limits<double>::max())
30 {
31 }
32
33 Value *ValueDouble::newInstance() const
34 {
35   return new ValueDouble;
36 }
37
38 ValueDouble::ValueDouble(double val):_data(val)
39 {
40 }
41
42 void ValueDouble::setDouble(double val) throw(INTERP_KERNEL::Exception)
43 {
44   _data=val;
45 }
46
47 void ValueDouble::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
48 {
49   std::string msg("Error var : "); msg+=var; msg+=" not numeric : use another expression evaluator !";
50   throw INTERP_KERNEL::Exception(msg.c_str());
51 }
52
53 void ValueDouble::positive() throw(INTERP_KERNEL::Exception)
54 {
55 }
56
57 void ValueDouble::negate() throw(INTERP_KERNEL::Exception)
58 {
59   _data=-_data;
60 }
61
62 void ValueDouble::sqrt() throw(INTERP_KERNEL::Exception)
63 {
64   _data=std::sqrt(_data);
65 }
66
67 void ValueDouble::cos() throw(INTERP_KERNEL::Exception)
68 {
69   _data=std::cos(_data);
70 }
71
72 void ValueDouble::sin() throw(INTERP_KERNEL::Exception)
73 {
74   _data=std::sin(_data);
75 }
76
77 void ValueDouble::tan() throw(INTERP_KERNEL::Exception)
78 {
79   _data=std::tan(_data);
80 }
81
82 void ValueDouble::abs() throw(INTERP_KERNEL::Exception)
83 {
84   if(_data<0.)
85     _data=-_data;
86 }
87
88 void ValueDouble::exp() throw(INTERP_KERNEL::Exception)
89 {
90   _data=std::exp(_data);
91 }
92
93 void ValueDouble::ln() throw(INTERP_KERNEL::Exception)
94 {
95   _data=std::log(_data);
96 }
97
98 void ValueDouble::log10() throw(INTERP_KERNEL::Exception)
99 {
100   _data=std::log10(_data);
101 }
102
103 Value *ValueDouble::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
104 {
105   const ValueDouble *valC=checkSameType(other);
106   return new ValueDouble(_data+valC->_data);
107 }
108
109 Value *ValueDouble::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
110 {
111   const ValueDouble *valC=checkSameType(other);
112   return new ValueDouble(_data-valC->_data);
113 }
114
115 Value *ValueDouble::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
116 {
117   const ValueDouble *valC=checkSameType(other);
118   return new ValueDouble(_data*valC->_data);
119 }
120
121 Value *ValueDouble::div(const Value *other) const throw(INTERP_KERNEL::Exception)
122 {
123   const ValueDouble *valC=checkSameType(other);
124   return new ValueDouble(_data/valC->_data);
125 }
126
127 Value *ValueDouble::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
128 {
129   const ValueDouble *valC=checkSameType(other);
130   return new ValueDouble(std::pow(_data,valC->_data));
131 }
132
133 Value *ValueDouble::max(const Value *other) const throw(INTERP_KERNEL::Exception)
134 {
135   const ValueDouble *valC=checkSameType(other);
136   return new ValueDouble(std::max(_data,valC->_data));
137 }
138
139 Value *ValueDouble::min(const Value *other) const throw(INTERP_KERNEL::Exception)
140 {
141   const ValueDouble *valC=checkSameType(other);
142   return new ValueDouble(std::min(_data,valC->_data));
143 }
144
145 Value *ValueDouble::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
146 {
147   const ValueDouble *valC=checkSameType(other);
148   return new ValueDouble(_data>valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
149 }
150
151 Value *ValueDouble::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
152 {
153   const ValueDouble *valC=checkSameType(other);
154   return new ValueDouble(_data<valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
155 }
156
157 Value *ValueDouble::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
158 {
159   const ValueDouble *theC=checkSameType(the);
160   const ValueDouble *elsC=checkSameType(els);
161   if(_data==std::numeric_limits<double>::max())
162     return new ValueDouble(theC->_data);
163   if(_data==-std::numeric_limits<double>::max())
164     return new ValueDouble(elsC->_data);
165   throw INTERP_KERNEL::Exception("ValueDouble::ifFunc : The fist element of ternary function if is not a binary op !");
166 }
167
168 const ValueDouble *ValueDouble::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception)
169 {
170   const ValueDouble *valC=dynamic_cast<const ValueDouble *>(val);
171   if(!valC)
172     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (double with other type) !");
173   return valC;
174 }
175
176 ValueUnit::ValueUnit()
177 {
178 }
179
180 Value *ValueUnit::newInstance() const
181 {
182   return new ValueUnit;
183 }
184
185 ValueUnit::ValueUnit(const DecompositionInUnitBase& unit):_data(unit)
186 {
187 }
188
189 void ValueUnit::setDouble(double val) throw(INTERP_KERNEL::Exception)
190 {
191   _data.tryToConvertInUnit(val);
192 }
193
194 void ValueUnit::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
195 {
196   double add,mul;
197   const short *projInBase=UnitDataBase::_uniqueMapForExpr.getInfoForUnit(var,add,mul);
198   _data.setInfo(projInBase,add,mul);
199 }
200
201 void ValueUnit::positive() throw(INTERP_KERNEL::Exception)
202 {
203   unsupportedOp(PositiveFunction::REPR);
204 }
205
206 void ValueUnit::negate() throw(INTERP_KERNEL::Exception)
207 {
208   _data.negate();
209 }
210
211 void ValueUnit::sqrt() throw(INTERP_KERNEL::Exception)
212 {
213   unsupportedOp(SqrtFunction::REPR);
214 }
215
216 void ValueUnit::cos() throw(INTERP_KERNEL::Exception)
217 {
218   unsupportedOp(CosFunction::REPR);
219 }
220
221 void ValueUnit::sin() throw(INTERP_KERNEL::Exception)
222 {
223   unsupportedOp(SinFunction::REPR);
224 }
225
226 void ValueUnit::tan() throw(INTERP_KERNEL::Exception)
227 {
228   unsupportedOp(TanFunction::REPR);
229 }
230
231 void ValueUnit::abs() throw(INTERP_KERNEL::Exception)
232 {
233   unsupportedOp(AbsFunction::REPR);
234 }
235
236 void ValueUnit::exp() throw(INTERP_KERNEL::Exception)
237 {
238   unsupportedOp(ExpFunction::REPR);
239 }
240
241 void ValueUnit::ln() throw(INTERP_KERNEL::Exception)
242 {
243   unsupportedOp(LnFunction::REPR);
244 }
245
246 void ValueUnit::log10() throw(INTERP_KERNEL::Exception)
247 {
248   unsupportedOp(Log10Function::REPR);
249 }
250
251 Value *ValueUnit::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
252 {
253   unsupportedOp(PlusFunction::REPR);
254   return 0;
255 }
256
257 Value *ValueUnit::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
258 {
259   unsupportedOp(MinusFunction::REPR);
260   return 0;
261 }
262
263 Value *ValueUnit::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
264 {
265   unsupportedOp(GreaterThanFunction::REPR);
266   return 0;
267 }
268
269 Value *ValueUnit::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
270 {
271   unsupportedOp(LowerThanFunction::REPR);
272   return 0;
273 }
274
275 Value *ValueUnit::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
276 {
277   unsupportedOp(IfFunction::REPR);
278   return 0;
279 }
280
281 Value *ValueUnit::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
282 {
283   const ValueUnit *valC=checkSameType(other);
284   DecompositionInUnitBase tmp=_data;
285   tmp*valC->getData();
286   return new ValueUnit(tmp);
287 }
288
289 Value *ValueUnit::div(const Value *other) const throw(INTERP_KERNEL::Exception)
290 {
291   const ValueUnit *valC=checkSameType(other);
292   DecompositionInUnitBase tmp=_data;
293   tmp/valC->getData();
294   return new ValueUnit(tmp);
295 }
296
297 Value *ValueUnit::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
298 {
299   const ValueUnit *valC=checkSameType(other);
300   DecompositionInUnitBase tmp=_data;
301   tmp^valC->getData();
302   return new ValueUnit(tmp);
303 }
304
305 Value *ValueUnit::max(const Value *other) const throw(INTERP_KERNEL::Exception)
306 {
307   unsupportedOp(MaxFunction::REPR);
308   return 0;
309 }
310
311 Value *ValueUnit::min(const Value *other) const throw(INTERP_KERNEL::Exception)
312 {
313   unsupportedOp(MinFunction::REPR);
314   return 0;
315 }
316
317 const ValueUnit *ValueUnit::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception)
318 {
319   const ValueUnit *valC=dynamic_cast<const ValueUnit *>(val);
320   if(!valC)
321     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (Units with other type) !");
322   return valC;
323 }
324
325 void ValueUnit::unsupportedOp(const char *type) throw(INTERP_KERNEL::Exception)
326 {
327   const char msg[]="Unsupported operation for units :";
328   std::string msgStr(msg);
329   msgStr+=type;
330   throw INTERP_KERNEL::Exception(msgStr.c_str());
331 }
332
333 ValueDoubleExpr::ValueDoubleExpr(int szDestData, const double *srcData):_sz_dest_data(szDestData),_dest_data(new double[_sz_dest_data]),_src_data(srcData)
334 {
335 }
336
337 ValueDoubleExpr::~ValueDoubleExpr()
338 {
339   delete [] _dest_data;
340 }
341
342 Value *ValueDoubleExpr::newInstance() const
343 {
344   return new ValueDoubleExpr(_sz_dest_data,_src_data);
345 }
346
347 void ValueDoubleExpr::setDouble(double val) throw(INTERP_KERNEL::Exception)
348 {
349   std::fill(_dest_data,_dest_data+_sz_dest_data,val);
350 }
351
352 void ValueDoubleExpr::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
353 {
354   if(fastPos==-2)
355     std::copy(_src_data,_src_data+_sz_dest_data,_dest_data);
356   else if(fastPos>-2)
357     std::fill(_dest_data,_dest_data+_sz_dest_data,_src_data[fastPos]);
358   else
359     {
360       std::fill(_dest_data,_dest_data+_sz_dest_data,0.);
361       _dest_data[-7-fastPos]=1.;
362     }
363 }
364
365 void ValueDoubleExpr::positive() throw(INTERP_KERNEL::Exception)
366 {
367 }
368
369 void ValueDoubleExpr::negate() throw(INTERP_KERNEL::Exception)
370 {
371   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::negate<double>());
372 }
373
374 void ValueDoubleExpr::sqrt() throw(INTERP_KERNEL::Exception)
375 {
376   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
377   if(it!=_dest_data+_sz_dest_data)
378     throw INTERP_KERNEL::Exception("Trying to apply sqrt on < 0. value !");
379   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sqrt));
380 }
381
382 void ValueDoubleExpr::cos() throw(INTERP_KERNEL::Exception)
383 {
384   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::cos));
385 }
386
387 void ValueDoubleExpr::sin() throw(INTERP_KERNEL::Exception)
388 {
389   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sin));
390 }
391
392 void ValueDoubleExpr::tan() throw(INTERP_KERNEL::Exception)
393 {
394   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::tan));
395 }
396
397 void ValueDoubleExpr::abs() throw(INTERP_KERNEL::Exception)
398 {
399   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(fabs));
400 }
401
402 void ValueDoubleExpr::exp() throw(INTERP_KERNEL::Exception)
403 {
404   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::exp));
405 }
406
407 void ValueDoubleExpr::ln() throw(INTERP_KERNEL::Exception)
408 {
409   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
410   if(it!=_dest_data+_sz_dest_data)
411     throw INTERP_KERNEL::Exception("Trying to apply neperian/natural log on <= 0. value !");
412   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log));
413 }
414
415 void ValueDoubleExpr::log10() throw(INTERP_KERNEL::Exception)
416 {
417   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
418   if(it!=_dest_data+_sz_dest_data)
419     throw INTERP_KERNEL::Exception("Trying to apply log10 on <= 0. value !");
420   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log10));
421 }
422
423 Value *ValueDoubleExpr::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
424 {
425   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
426   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
427   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::plus<double>());
428   return ret;
429 }
430
431 Value *ValueDoubleExpr::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
432 {
433   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
434   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
435   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::minus<double>());
436   return ret;
437 }
438
439 Value *ValueDoubleExpr::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
440 {
441   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
442   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
443   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::multiplies<double>());
444   return ret;
445 }
446
447 Value *ValueDoubleExpr::div(const Value *other) const throw(INTERP_KERNEL::Exception)
448 {
449   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
450   double *it=std::find(otherC->getData(),otherC->getData()+_sz_dest_data,0.);
451   if(it!=otherC->getData()+_sz_dest_data)
452     throw INTERP_KERNEL::Exception("Trying to operate division by 0. !");
453   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
454   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::divides<double>());
455   return ret;
456 }
457
458 Value *ValueDoubleExpr::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
459 {
460   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
461   double p=otherC->getData()[0];
462   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
463   if(it!=_dest_data+_sz_dest_data)
464     throw INTERP_KERNEL::Exception("Trying to operate pow(a,b) with a<0. !");
465   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
466   std::transform(_dest_data,_dest_data+_sz_dest_data,ret->getData(),std::bind2nd(std::ptr_fun<double,double,double>(std::pow),p));
467   return ret;
468 }
469
470 Value *ValueDoubleExpr::max(const Value *other) const throw(INTERP_KERNEL::Exception)
471 {
472   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
473   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
474   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::max));
475   return ret;
476 }
477
478 Value *ValueDoubleExpr::min(const Value *other) const throw(INTERP_KERNEL::Exception)
479 {
480   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
481   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
482   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::min));
483   return ret;
484 }
485
486 Value *ValueDoubleExpr::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
487 {
488   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
489   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
490   for(int i=0;i<_sz_dest_data;i++)
491     if(_dest_data[i]<=otherC->getData()[i])
492       {
493         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
494         return ret;
495       }
496   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
497   return ret;
498 }
499
500 Value *ValueDoubleExpr::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
501 {
502   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
503   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
504   for(int i=0;i<_sz_dest_data;i++)
505     if(_dest_data[i]>=otherC->getData()[i])
506       {
507         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
508         return ret;
509       }
510   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
511   return ret;
512 }
513
514 Value *ValueDoubleExpr::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
515 {
516   const ValueDoubleExpr *theC=static_cast<const ValueDoubleExpr *>(the);
517   const ValueDoubleExpr *elsC=static_cast<const ValueDoubleExpr *>(els);
518   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
519   bool okmax=true;
520   bool okmin=true;
521   for(int i=0;i<_sz_dest_data && (okmax || okmin);i++)
522     {
523       okmax=_dest_data[i]==std::numeric_limits<double>::max();
524       okmin=_dest_data[i]==-std::numeric_limits<double>::max();
525     }
526   if(okmax || okmin)
527     {
528       if(okmax)
529         std::copy(theC->getData(),theC->getData()+_sz_dest_data,ret->getData());
530       else
531         std::copy(elsC->getData(),elsC->getData()+_sz_dest_data,ret->getData());
532       return ret;
533     }
534   else
535     {
536       throw INTERP_KERNEL::Exception("ValueDoubleExpr::ifFunc : first parameter of ternary func is NOT a consequence of a boolean op !");
537     }
538 }