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