Salome HOME
merge conflict
[modules/med.git] / src / medtool / src / INTERP_KERNEL / ExprEval / InterpKernelValue.cxx
1 // Copyright (C) 2007-2015  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, or (at your option) any later version.
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 // Author : Anthony Geay (CEA/DEN)
20
21 #include "InterpKernelValue.hxx"
22 #include "InterpKernelFunction.hxx"
23
24 #include <cmath>
25 #include <limits>
26 #include <algorithm>
27
28 using namespace INTERP_KERNEL;
29
30 ValueDouble::ValueDouble():_data(std::numeric_limits<double>::max())
31 {
32 }
33
34 Value *ValueDouble::newInstance() const
35 {
36   return new ValueDouble;
37 }
38
39 ValueDouble::ValueDouble(double val):_data(val)
40 {
41 }
42
43 void ValueDouble::setDouble(double val)
44 {
45   _data=val;
46 }
47
48 void ValueDouble::setVarname(int fastPos, const std::string& var)
49 {
50   std::string msg("Error var : "); msg+=var; msg+=" not numeric : use another expression evaluator !";
51   throw INTERP_KERNEL::Exception(msg.c_str());
52 }
53
54 void ValueDouble::positive()
55 {
56 }
57
58 void ValueDouble::negate()
59 {
60   _data=-_data;
61 }
62
63 void ValueDouble::sqrt()
64 {
65   _data=std::sqrt(_data);
66 }
67
68 void ValueDouble::cos()
69 {
70   _data=std::cos(_data);
71 }
72
73 void ValueDouble::sin()
74 {
75   _data=std::sin(_data);
76 }
77
78 void ValueDouble::tan()
79 {
80   _data=std::tan(_data);
81 }
82
83 void ValueDouble::acos()
84 {
85   _data=std::acos(_data);
86 }
87
88 void ValueDouble::asin()
89 {
90   _data=std::asin(_data);
91 }
92
93 void ValueDouble::atan()
94 {
95   _data=std::atan(_data);
96 }
97
98 void ValueDouble::cosh()
99 {
100   _data=std::cosh(_data);
101 }
102
103 void ValueDouble::sinh()
104 {
105   _data=std::sinh(_data);
106 }
107
108 void ValueDouble::tanh()
109 {
110   _data=std::tanh(_data);
111 }
112
113 void ValueDouble::abs()
114 {
115   if(_data<0.)
116     _data=-_data;
117 }
118
119 void ValueDouble::exp()
120 {
121   _data=std::exp(_data);
122 }
123
124 void ValueDouble::ln()
125 {
126   _data=std::log(_data);
127 }
128
129 void ValueDouble::log10()
130 {
131   _data=std::log10(_data);
132 }
133
134 Value *ValueDouble::plus(const Value *other) const
135 {
136   const ValueDouble *valC=checkSameType(other);
137   return new ValueDouble(_data+valC->_data);
138 }
139
140 Value *ValueDouble::minus(const Value *other) const
141 {
142   const ValueDouble *valC=checkSameType(other);
143   return new ValueDouble(_data-valC->_data);
144 }
145
146 Value *ValueDouble::mult(const Value *other) const
147 {
148   const ValueDouble *valC=checkSameType(other);
149   return new ValueDouble(_data*valC->_data);
150 }
151
152 Value *ValueDouble::div(const Value *other) const
153 {
154   const ValueDouble *valC=checkSameType(other);
155   return new ValueDouble(_data/valC->_data);
156 }
157
158 Value *ValueDouble::pow(const Value *other) const
159 {
160   const ValueDouble *valC=checkSameType(other);
161   return new ValueDouble(std::pow(_data,valC->_data));
162 }
163
164 Value *ValueDouble::max(const Value *other) const
165 {
166   const ValueDouble *valC=checkSameType(other);
167   return new ValueDouble(std::max(_data,valC->_data));
168 }
169
170 Value *ValueDouble::min(const Value *other) const
171 {
172   const ValueDouble *valC=checkSameType(other);
173   return new ValueDouble(std::min(_data,valC->_data));
174 }
175
176 Value *ValueDouble::greaterThan(const Value *other) const
177 {
178   const ValueDouble *valC=checkSameType(other);
179   return new ValueDouble(_data>valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
180 }
181
182 Value *ValueDouble::lowerThan(const Value *other) const
183 {
184   const ValueDouble *valC=checkSameType(other);
185   return new ValueDouble(_data<valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
186 }
187
188 Value *ValueDouble::ifFunc(const Value *the, const Value *els) const
189 {
190   const ValueDouble *theC=checkSameType(the);
191   const ValueDouble *elsC=checkSameType(els);
192   if(_data==std::numeric_limits<double>::max())
193     return new ValueDouble(theC->_data);
194   if(_data==-std::numeric_limits<double>::max())
195     return new ValueDouble(elsC->_data);
196   throw INTERP_KERNEL::Exception("ValueDouble::ifFunc : The fist element of ternary function if is not a binary op !");
197 }
198
199 const ValueDouble *ValueDouble::checkSameType(const Value *val)
200 {
201   const ValueDouble *valC=dynamic_cast<const ValueDouble *>(val);
202   if(!valC)
203     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (double with other type) !");
204   return valC;
205 }
206
207 ValueUnit::ValueUnit()
208 {
209 }
210
211 Value *ValueUnit::newInstance() const
212 {
213   return new ValueUnit;
214 }
215
216 ValueUnit::ValueUnit(const DecompositionInUnitBase& unit):_data(unit)
217 {
218 }
219
220 void ValueUnit::setDouble(double val)
221 {
222   _data.tryToConvertInUnit(val);
223 }
224
225 void ValueUnit::setVarname(int fastPos, const std::string& var)
226 {
227   double add,mul;
228   const short *projInBase=UnitDataBase::_uniqueMapForExpr.getInfoForUnit(var,add,mul);
229   _data.setInfo(projInBase,add,mul);
230 }
231
232 void ValueUnit::positive()
233 {
234   unsupportedOp(PositiveFunction::REPR);
235 }
236
237 void ValueUnit::negate()
238 {
239   _data.negate();
240 }
241
242 void ValueUnit::sqrt()
243 {
244   unsupportedOp(SqrtFunction::REPR);
245 }
246
247 void ValueUnit::cos()
248 {
249   unsupportedOp(CosFunction::REPR);
250 }
251
252 void ValueUnit::sin()
253 {
254   unsupportedOp(SinFunction::REPR);
255 }
256
257 void ValueUnit::tan()
258 {
259   unsupportedOp(TanFunction::REPR);
260 }
261
262 void ValueUnit::acos()
263 {
264   unsupportedOp(ACosFunction::REPR);
265 }
266
267 void ValueUnit::asin()
268 {
269   unsupportedOp(ASinFunction::REPR);
270 }
271
272 void ValueUnit::atan()
273 {
274   unsupportedOp(ATanFunction::REPR);
275 }
276
277 void ValueUnit::cosh()
278 {
279   unsupportedOp(CoshFunction::REPR);
280 }
281
282 void ValueUnit::sinh()
283 {
284   unsupportedOp(SinhFunction::REPR);
285 }
286
287 void ValueUnit::tanh()
288 {
289   unsupportedOp(TanhFunction::REPR);
290 }
291
292 void ValueUnit::abs()
293 {
294   unsupportedOp(AbsFunction::REPR);
295 }
296
297 void ValueUnit::exp()
298 {
299   unsupportedOp(ExpFunction::REPR);
300 }
301
302 void ValueUnit::ln()
303 {
304   unsupportedOp(LnFunction::REPR);
305 }
306
307 void ValueUnit::log10()
308 {
309   unsupportedOp(Log10Function::REPR);
310 }
311
312 Value *ValueUnit::plus(const Value *other) const
313 {
314   unsupportedOp(PlusFunction::REPR);
315   return 0;
316 }
317
318 Value *ValueUnit::minus(const Value *other) const
319 {
320   unsupportedOp(MinusFunction::REPR);
321   return 0;
322 }
323
324 Value *ValueUnit::greaterThan(const Value *other) const
325 {
326   unsupportedOp(GreaterThanFunction::REPR);
327   return 0;
328 }
329
330 Value *ValueUnit::lowerThan(const Value *other) const
331 {
332   unsupportedOp(LowerThanFunction::REPR);
333   return 0;
334 }
335
336 Value *ValueUnit::ifFunc(const Value *the, const Value *els) const
337 {
338   unsupportedOp(IfFunction::REPR);
339   return 0;
340 }
341
342 Value *ValueUnit::mult(const Value *other) const
343 {
344   const ValueUnit *valC=checkSameType(other);
345   DecompositionInUnitBase tmp=_data;
346   tmp*valC->getData();
347   return new ValueUnit(tmp);
348 }
349
350 Value *ValueUnit::div(const Value *other) const
351 {
352   const ValueUnit *valC=checkSameType(other);
353   DecompositionInUnitBase tmp=_data;
354   tmp/valC->getData();
355   return new ValueUnit(tmp);
356 }
357
358 Value *ValueUnit::pow(const Value *other) const
359 {
360   const ValueUnit *valC=checkSameType(other);
361   DecompositionInUnitBase tmp=_data;
362   tmp^valC->getData();
363   return new ValueUnit(tmp);
364 }
365
366 Value *ValueUnit::max(const Value *other) const
367 {
368   unsupportedOp(MaxFunction::REPR);
369   return 0;
370 }
371
372 Value *ValueUnit::min(const Value *other) const
373 {
374   unsupportedOp(MinFunction::REPR);
375   return 0;
376 }
377
378 const ValueUnit *ValueUnit::checkSameType(const Value *val)
379 {
380   const ValueUnit *valC=dynamic_cast<const ValueUnit *>(val);
381   if(!valC)
382     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (Units with other type) !");
383   return valC;
384 }
385
386 void ValueUnit::unsupportedOp(const char *type)
387 {
388   const char msg[]="Unsupported operation for units :";
389   std::string msgStr(msg);
390   msgStr+=type;
391   throw INTERP_KERNEL::Exception(msgStr.c_str());
392 }
393
394 ValueDoubleExpr::ValueDoubleExpr(int szDestData, const double *srcData):_sz_dest_data(szDestData),_dest_data(new double[_sz_dest_data]),_src_data(srcData)
395 {
396 }
397
398 ValueDoubleExpr::~ValueDoubleExpr()
399 {
400   delete [] _dest_data;
401 }
402
403 Value *ValueDoubleExpr::newInstance() const
404 {
405   return new ValueDoubleExpr(_sz_dest_data,_src_data);
406 }
407
408 void ValueDoubleExpr::setDouble(double val)
409 {
410   std::fill(_dest_data,_dest_data+_sz_dest_data,val);
411 }
412
413 void ValueDoubleExpr::setVarname(int fastPos, const std::string& var)
414 {
415   if(fastPos==-2)
416     std::copy(_src_data,_src_data+_sz_dest_data,_dest_data);
417   else if(fastPos>-2)
418     std::fill(_dest_data,_dest_data+_sz_dest_data,_src_data[fastPos]);
419   else
420     {
421       std::fill(_dest_data,_dest_data+_sz_dest_data,0.);
422       _dest_data[-7-fastPos]=1.;
423     }
424 }
425
426 void ValueDoubleExpr::positive()
427 {
428 }
429
430 void ValueDoubleExpr::negate()
431 {
432   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::negate<double>());
433 }
434
435 void ValueDoubleExpr::sqrt()
436 {
437   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
438   if(it!=_dest_data+_sz_dest_data)
439     throw INTERP_KERNEL::Exception("Trying to apply sqrt on < 0. value !");
440   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sqrt));
441 }
442
443 void ValueDoubleExpr::cos()
444 {
445   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::cos));
446 }
447
448 void ValueDoubleExpr::sin()
449 {
450   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sin));
451 }
452
453 void ValueDoubleExpr::tan()
454 {
455   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::tan));
456 }
457
458 void ValueDoubleExpr::acos()
459 {
460   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),-1.));
461   if(it!=_dest_data+_sz_dest_data)
462     throw INTERP_KERNEL::Exception("Trying to apply acos on < 1. value !");
463   it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::greater<double>(),1.));
464   if(it!=_dest_data+_sz_dest_data)
465     throw INTERP_KERNEL::Exception("Trying to apply acos on > 1. value !");
466   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::acos));
467 }
468
469 void ValueDoubleExpr::asin()
470 {
471    double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),-1.));
472    if(it!=_dest_data+_sz_dest_data)
473     throw INTERP_KERNEL::Exception("Trying to apply asin on < 1. value !");
474   it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::greater<double>(),1.));
475   if(it!=_dest_data+_sz_dest_data)
476     throw INTERP_KERNEL::Exception("Trying to apply asin on > 1. value !");
477   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::asin));
478 }
479
480 void ValueDoubleExpr::atan()
481 {
482   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::atan));
483 }
484
485 void ValueDoubleExpr::cosh()
486 {
487   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::cosh));
488 }
489
490 void ValueDoubleExpr::sinh()
491 {
492   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sinh));
493 }
494
495 void ValueDoubleExpr::tanh()
496 {
497   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::tanh));
498 }
499
500 void ValueDoubleExpr::abs()
501 {
502   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(fabs));
503 }
504
505 void ValueDoubleExpr::exp()
506 {
507   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::exp));
508 }
509
510 void ValueDoubleExpr::ln()
511 {
512   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
513   if(it!=_dest_data+_sz_dest_data)
514     throw INTERP_KERNEL::Exception("Trying to apply neperian/natural log on <= 0. value !");
515   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log));
516 }
517
518 void ValueDoubleExpr::log10()
519 {
520   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
521   if(it!=_dest_data+_sz_dest_data)
522     throw INTERP_KERNEL::Exception("Trying to apply log10 on <= 0. value !");
523   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log10));
524 }
525
526 Value *ValueDoubleExpr::plus(const Value *other) const
527 {
528   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
529   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
530   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::plus<double>());
531   return ret;
532 }
533
534 Value *ValueDoubleExpr::minus(const Value *other) const
535 {
536   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
537   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
538   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::minus<double>());
539   return ret;
540 }
541
542 Value *ValueDoubleExpr::mult(const Value *other) const
543 {
544   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
545   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
546   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::multiplies<double>());
547   return ret;
548 }
549
550 Value *ValueDoubleExpr::div(const Value *other) const
551 {
552   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
553   double *it=std::find(otherC->getData(),otherC->getData()+_sz_dest_data,0.);
554   if(it!=otherC->getData()+_sz_dest_data)
555     throw INTERP_KERNEL::Exception("Trying to operate division by 0. !");
556   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
557   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::divides<double>());
558   return ret;
559 }
560
561 Value *ValueDoubleExpr::pow(const Value *other) const
562 {
563   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
564   double p=otherC->getData()[0];
565   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
566   if(it!=_dest_data+_sz_dest_data)
567     throw INTERP_KERNEL::Exception("Trying to operate pow(a,b) with a<0. !");
568   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
569   std::transform(_dest_data,_dest_data+_sz_dest_data,ret->getData(),std::bind2nd(std::ptr_fun<double,double,double>(std::pow),p));
570   return ret;
571 }
572
573 Value *ValueDoubleExpr::max(const Value *other) const
574 {
575   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
576   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
577   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::max));
578   return ret;
579 }
580
581 Value *ValueDoubleExpr::min(const Value *other) const
582 {
583   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
584   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
585   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::min));
586   return ret;
587 }
588
589 Value *ValueDoubleExpr::greaterThan(const Value *other) const
590 {
591   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
592   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
593   for(int i=0;i<_sz_dest_data;i++)
594     if(_dest_data[i]<=otherC->getData()[i])
595       {
596         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
597         return ret;
598       }
599   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
600   return ret;
601 }
602
603 Value *ValueDoubleExpr::lowerThan(const Value *other) const
604 {
605   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
606   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
607   for(int i=0;i<_sz_dest_data;i++)
608     if(_dest_data[i]>=otherC->getData()[i])
609       {
610         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
611         return ret;
612       }
613   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
614   return ret;
615 }
616
617 Value *ValueDoubleExpr::ifFunc(const Value *the, const Value *els) const
618 {
619   const ValueDoubleExpr *theC=static_cast<const ValueDoubleExpr *>(the);
620   const ValueDoubleExpr *elsC=static_cast<const ValueDoubleExpr *>(els);
621   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
622   bool okmax=true;
623   bool okmin=true;
624   for(int i=0;i<_sz_dest_data && (okmax || okmin);i++)
625     {
626       okmax=_dest_data[i]==std::numeric_limits<double>::max();
627       okmin=_dest_data[i]==-std::numeric_limits<double>::max();
628     }
629   if(okmax || okmin)
630     {
631       if(okmax)
632         std::copy(theC->getData(),theC->getData()+_sz_dest_data,ret->getData());
633       else
634         std::copy(elsC->getData(),elsC->getData()+_sz_dest_data,ret->getData());
635       return ret;
636     }
637   else
638     {
639       throw INTERP_KERNEL::Exception("ValueDoubleExpr::ifFunc : first parameter of ternary func is NOT a consequence of a boolean op !");
640     }
641 }