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