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