Back to index

salome-med  6.5.0
InterpKernelValue.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D
00002 //
00003 // This library is free software; you can redistribute it and/or
00004 // modify it under the terms of the GNU Lesser General Public
00005 // License as published by the Free Software Foundation; either
00006 // version 2.1 of the License.
00007 //
00008 // This library is distributed in the hope that it will be useful,
00009 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00010 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00011 // Lesser General Public License for more details.
00012 //
00013 // You should have received a copy of the GNU Lesser General Public
00014 // License along with this library; if not, write to the Free Software
00015 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00016 //
00017 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00018 //
00019 
00020 #include "InterpKernelValue.hxx"
00021 #include "InterpKernelFunction.hxx"
00022 
00023 #include <cmath>
00024 #include <limits>
00025 #include <algorithm>
00026 
00027 using namespace INTERP_KERNEL;
00028 
00029 ValueDouble::ValueDouble():_data(std::numeric_limits<double>::max())
00030 {
00031 }
00032 
00033 Value *ValueDouble::newInstance() const
00034 {
00035   return new ValueDouble;
00036 }
00037 
00038 ValueDouble::ValueDouble(double val):_data(val)
00039 {
00040 }
00041 
00042 void ValueDouble::setDouble(double val) throw(INTERP_KERNEL::Exception)
00043 {
00044   _data=val;
00045 }
00046 
00047 void ValueDouble::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
00048 {
00049   std::string msg("Error var : "); msg+=var; msg+=" not numeric : use another expression evaluator !";
00050   throw INTERP_KERNEL::Exception(msg.c_str());
00051 }
00052 
00053 void ValueDouble::positive() throw(INTERP_KERNEL::Exception)
00054 {
00055 }
00056 
00057 void ValueDouble::negate() throw(INTERP_KERNEL::Exception)
00058 {
00059   _data=-_data;
00060 }
00061 
00062 void ValueDouble::sqrt() throw(INTERP_KERNEL::Exception)
00063 {
00064   _data=std::sqrt(_data);
00065 }
00066 
00067 void ValueDouble::cos() throw(INTERP_KERNEL::Exception)
00068 {
00069   _data=std::cos(_data);
00070 }
00071 
00072 void ValueDouble::sin() throw(INTERP_KERNEL::Exception)
00073 {
00074   _data=std::sin(_data);
00075 }
00076 
00077 void ValueDouble::tan() throw(INTERP_KERNEL::Exception)
00078 {
00079   _data=std::tan(_data);
00080 }
00081 
00082 void ValueDouble::abs() throw(INTERP_KERNEL::Exception)
00083 {
00084   if(_data<0.)
00085     _data=-_data;
00086 }
00087 
00088 void ValueDouble::exp() throw(INTERP_KERNEL::Exception)
00089 {
00090   _data=std::exp(_data);
00091 }
00092 
00093 void ValueDouble::ln() throw(INTERP_KERNEL::Exception)
00094 {
00095   _data=std::log(_data);
00096 }
00097 
00098 void ValueDouble::log10() throw(INTERP_KERNEL::Exception)
00099 {
00100   _data=std::log10(_data);
00101 }
00102 
00103 Value *ValueDouble::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
00104 {
00105   const ValueDouble *valC=checkSameType(other);
00106   return new ValueDouble(_data+valC->_data);
00107 }
00108 
00109 Value *ValueDouble::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
00110 {
00111   const ValueDouble *valC=checkSameType(other);
00112   return new ValueDouble(_data-valC->_data);
00113 }
00114 
00115 Value *ValueDouble::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
00116 {
00117   const ValueDouble *valC=checkSameType(other);
00118   return new ValueDouble(_data*valC->_data);
00119 }
00120 
00121 Value *ValueDouble::div(const Value *other) const throw(INTERP_KERNEL::Exception)
00122 {
00123   const ValueDouble *valC=checkSameType(other);
00124   return new ValueDouble(_data/valC->_data);
00125 }
00126 
00127 Value *ValueDouble::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
00128 {
00129   const ValueDouble *valC=checkSameType(other);
00130   return new ValueDouble(std::pow(_data,valC->_data));
00131 }
00132 
00133 Value *ValueDouble::max(const Value *other) const throw(INTERP_KERNEL::Exception)
00134 {
00135   const ValueDouble *valC=checkSameType(other);
00136   return new ValueDouble(std::max(_data,valC->_data));
00137 }
00138 
00139 Value *ValueDouble::min(const Value *other) const throw(INTERP_KERNEL::Exception)
00140 {
00141   const ValueDouble *valC=checkSameType(other);
00142   return new ValueDouble(std::min(_data,valC->_data));
00143 }
00144 
00145 Value *ValueDouble::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00146 {
00147   const ValueDouble *valC=checkSameType(other);
00148   return new ValueDouble(_data>valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
00149 }
00150 
00151 Value *ValueDouble::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00152 {
00153   const ValueDouble *valC=checkSameType(other);
00154   return new ValueDouble(_data<valC->_data?std::numeric_limits<double>::max():-std::numeric_limits<double>::max());
00155 }
00156 
00157 Value *ValueDouble::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
00158 {
00159   const ValueDouble *theC=checkSameType(the);
00160   const ValueDouble *elsC=checkSameType(els);
00161   if(_data==std::numeric_limits<double>::max())
00162     return new ValueDouble(theC->_data);
00163   if(_data==-std::numeric_limits<double>::max())
00164     return new ValueDouble(elsC->_data);
00165   throw INTERP_KERNEL::Exception("ValueDouble::ifFunc : The fist element of ternary function if is not a binary op !");
00166 }
00167 
00168 const ValueDouble *ValueDouble::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception)
00169 {
00170   const ValueDouble *valC=dynamic_cast<const ValueDouble *>(val);
00171   if(!valC)
00172     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (double with other type) !");
00173   return valC;
00174 }
00175 
00176 ValueUnit::ValueUnit()
00177 {
00178 }
00179 
00180 Value *ValueUnit::newInstance() const
00181 {
00182   return new ValueUnit;
00183 }
00184 
00185 ValueUnit::ValueUnit(const DecompositionInUnitBase& unit):_data(unit)
00186 {
00187 }
00188 
00189 void ValueUnit::setDouble(double val) throw(INTERP_KERNEL::Exception)
00190 {
00191   _data.tryToConvertInUnit(val);
00192 }
00193 
00194 void ValueUnit::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
00195 {
00196   double add,mul;
00197   const short *projInBase=UnitDataBase::_uniqueMapForExpr.getInfoForUnit(var,add,mul);
00198   _data.setInfo(projInBase,add,mul);
00199 }
00200 
00201 void ValueUnit::positive() throw(INTERP_KERNEL::Exception)
00202 {
00203   unsupportedOp(PositiveFunction::REPR);
00204 }
00205 
00206 void ValueUnit::negate() throw(INTERP_KERNEL::Exception)
00207 {
00208   _data.negate();
00209 }
00210 
00211 void ValueUnit::sqrt() throw(INTERP_KERNEL::Exception)
00212 {
00213   unsupportedOp(SqrtFunction::REPR);
00214 }
00215 
00216 void ValueUnit::cos() throw(INTERP_KERNEL::Exception)
00217 {
00218   unsupportedOp(CosFunction::REPR);
00219 }
00220 
00221 void ValueUnit::sin() throw(INTERP_KERNEL::Exception)
00222 {
00223   unsupportedOp(SinFunction::REPR);
00224 }
00225 
00226 void ValueUnit::tan() throw(INTERP_KERNEL::Exception)
00227 {
00228   unsupportedOp(TanFunction::REPR);
00229 }
00230 
00231 void ValueUnit::abs() throw(INTERP_KERNEL::Exception)
00232 {
00233   unsupportedOp(AbsFunction::REPR);
00234 }
00235 
00236 void ValueUnit::exp() throw(INTERP_KERNEL::Exception)
00237 {
00238   unsupportedOp(ExpFunction::REPR);
00239 }
00240 
00241 void ValueUnit::ln() throw(INTERP_KERNEL::Exception)
00242 {
00243   unsupportedOp(LnFunction::REPR);
00244 }
00245 
00246 void ValueUnit::log10() throw(INTERP_KERNEL::Exception)
00247 {
00248   unsupportedOp(Log10Function::REPR);
00249 }
00250 
00251 Value *ValueUnit::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
00252 {
00253   unsupportedOp(PlusFunction::REPR);
00254   return 0;
00255 }
00256 
00257 Value *ValueUnit::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
00258 {
00259   unsupportedOp(MinusFunction::REPR);
00260   return 0;
00261 }
00262 
00263 Value *ValueUnit::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00264 {
00265   unsupportedOp(GreaterThanFunction::REPR);
00266   return 0;
00267 }
00268 
00269 Value *ValueUnit::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00270 {
00271   unsupportedOp(LowerThanFunction::REPR);
00272   return 0;
00273 }
00274 
00275 Value *ValueUnit::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
00276 {
00277   unsupportedOp(IfFunction::REPR);
00278   return 0;
00279 }
00280 
00281 Value *ValueUnit::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
00282 {
00283   const ValueUnit *valC=checkSameType(other);
00284   DecompositionInUnitBase tmp=_data;
00285   tmp*valC->getData();
00286   return new ValueUnit(tmp);
00287 }
00288 
00289 Value *ValueUnit::div(const Value *other) const throw(INTERP_KERNEL::Exception)
00290 {
00291   const ValueUnit *valC=checkSameType(other);
00292   DecompositionInUnitBase tmp=_data;
00293   tmp/valC->getData();
00294   return new ValueUnit(tmp);
00295 }
00296 
00297 Value *ValueUnit::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
00298 {
00299   const ValueUnit *valC=checkSameType(other);
00300   DecompositionInUnitBase tmp=_data;
00301   tmp^valC->getData();
00302   return new ValueUnit(tmp);
00303 }
00304 
00305 Value *ValueUnit::max(const Value *other) const throw(INTERP_KERNEL::Exception)
00306 {
00307   unsupportedOp(MaxFunction::REPR);
00308   return 0;
00309 }
00310 
00311 Value *ValueUnit::min(const Value *other) const throw(INTERP_KERNEL::Exception)
00312 {
00313   unsupportedOp(MinFunction::REPR);
00314   return 0;
00315 }
00316 
00317 const ValueUnit *ValueUnit::checkSameType(const Value *val) throw(INTERP_KERNEL::Exception)
00318 {
00319   const ValueUnit *valC=dynamic_cast<const ValueUnit *>(val);
00320   if(!valC)
00321     throw INTERP_KERNEL::Exception("Trying to operate on non homogeneous Values (Units with other type) !");
00322   return valC;
00323 }
00324 
00325 void ValueUnit::unsupportedOp(const char *type) throw(INTERP_KERNEL::Exception)
00326 {
00327   const char msg[]="Unsupported operation for units :";
00328   std::string msgStr(msg);
00329   msgStr+=type;
00330   throw INTERP_KERNEL::Exception(msgStr.c_str());
00331 }
00332 
00333 ValueDoubleExpr::ValueDoubleExpr(int szDestData, const double *srcData):_sz_dest_data(szDestData),_dest_data(new double[_sz_dest_data]),_src_data(srcData)
00334 {
00335 }
00336 
00337 ValueDoubleExpr::~ValueDoubleExpr()
00338 {
00339   delete [] _dest_data;
00340 }
00341 
00342 Value *ValueDoubleExpr::newInstance() const
00343 {
00344   return new ValueDoubleExpr(_sz_dest_data,_src_data);
00345 }
00346 
00347 void ValueDoubleExpr::setDouble(double val) throw(INTERP_KERNEL::Exception)
00348 {
00349   std::fill(_dest_data,_dest_data+_sz_dest_data,val);
00350 }
00351 
00352 void ValueDoubleExpr::setVarname(int fastPos, const std::string& var) throw(INTERP_KERNEL::Exception)
00353 {
00354   if(fastPos==-2)
00355     std::copy(_src_data,_src_data+_sz_dest_data,_dest_data);
00356   else if(fastPos>-2)
00357     std::fill(_dest_data,_dest_data+_sz_dest_data,_src_data[fastPos]);
00358   else
00359     {
00360       std::fill(_dest_data,_dest_data+_sz_dest_data,0.);
00361       _dest_data[-7-fastPos]=1.;
00362     }
00363 }
00364 
00365 void ValueDoubleExpr::positive() throw(INTERP_KERNEL::Exception)
00366 {
00367 }
00368 
00369 void ValueDoubleExpr::negate() throw(INTERP_KERNEL::Exception)
00370 {
00371   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::negate<double>());
00372 }
00373 
00374 void ValueDoubleExpr::sqrt() throw(INTERP_KERNEL::Exception)
00375 {
00376   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
00377   if(it!=_dest_data+_sz_dest_data)
00378     throw INTERP_KERNEL::Exception("Trying to apply sqrt on < 0. value !");
00379   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sqrt));
00380 }
00381 
00382 void ValueDoubleExpr::cos() throw(INTERP_KERNEL::Exception)
00383 {
00384   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::cos));
00385 }
00386 
00387 void ValueDoubleExpr::sin() throw(INTERP_KERNEL::Exception)
00388 {
00389   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::sin));
00390 }
00391 
00392 void ValueDoubleExpr::tan() throw(INTERP_KERNEL::Exception)
00393 {
00394   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::tan));
00395 }
00396 
00397 void ValueDoubleExpr::abs() throw(INTERP_KERNEL::Exception)
00398 {
00399   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(fabs));
00400 }
00401 
00402 void ValueDoubleExpr::exp() throw(INTERP_KERNEL::Exception)
00403 {
00404   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::exp));
00405 }
00406 
00407 void ValueDoubleExpr::ln() throw(INTERP_KERNEL::Exception)
00408 {
00409   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
00410   if(it!=_dest_data+_sz_dest_data)
00411     throw INTERP_KERNEL::Exception("Trying to apply neperian/natural log on <= 0. value !");
00412   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log));
00413 }
00414 
00415 void ValueDoubleExpr::log10() throw(INTERP_KERNEL::Exception)
00416 {
00417   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less_equal<double>(),0.));
00418   if(it!=_dest_data+_sz_dest_data)
00419     throw INTERP_KERNEL::Exception("Trying to apply log10 on <= 0. value !");
00420   std::transform(_dest_data,_dest_data+_sz_dest_data,_dest_data,std::ptr_fun<double,double>(std::log10));
00421 }
00422 
00423 Value *ValueDoubleExpr::plus(const Value *other) const throw(INTERP_KERNEL::Exception)
00424 {
00425   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00426   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00427   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::plus<double>());
00428   return ret;
00429 }
00430 
00431 Value *ValueDoubleExpr::minus(const Value *other) const throw(INTERP_KERNEL::Exception)
00432 {
00433   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00434   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00435   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::minus<double>());
00436   return ret;
00437 }
00438 
00439 Value *ValueDoubleExpr::mult(const Value *other) const throw(INTERP_KERNEL::Exception)
00440 {
00441   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00442   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00443   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::multiplies<double>());
00444   return ret;
00445 }
00446 
00447 Value *ValueDoubleExpr::div(const Value *other) const throw(INTERP_KERNEL::Exception)
00448 {
00449   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00450   double *it=std::find(otherC->getData(),otherC->getData()+_sz_dest_data,0.);
00451   if(it!=otherC->getData()+_sz_dest_data)
00452     throw INTERP_KERNEL::Exception("Trying to operate division by 0. !");
00453   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00454   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::divides<double>());
00455   return ret;
00456 }
00457 
00458 Value *ValueDoubleExpr::pow(const Value *other) const throw(INTERP_KERNEL::Exception)
00459 {
00460   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00461   double p=otherC->getData()[0];
00462   double *it=std::find_if(_dest_data,_dest_data+_sz_dest_data,std::bind2nd(std::less<double>(),0.));
00463   if(it!=_dest_data+_sz_dest_data)
00464     throw INTERP_KERNEL::Exception("Trying to operate pow(a,b) with a<0. !");
00465   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00466   std::transform(_dest_data,_dest_data+_sz_dest_data,ret->getData(),std::bind2nd(std::ptr_fun<double,double,double>(std::pow),p));
00467   return ret;
00468 }
00469 
00470 Value *ValueDoubleExpr::max(const Value *other) const throw(INTERP_KERNEL::Exception)
00471 {
00472   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00473   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00474   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::max));
00475   return ret;
00476 }
00477 
00478 Value *ValueDoubleExpr::min(const Value *other) const throw(INTERP_KERNEL::Exception)
00479 {
00480   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00481   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00482   std::transform(_dest_data,_dest_data+_sz_dest_data,otherC->getData(),ret->getData(),std::ptr_fun<const double&, const double&, const double& >(std::min));
00483   return ret;
00484 }
00485 
00486 Value *ValueDoubleExpr::greaterThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00487 {
00488   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00489   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00490   for(int i=0;i<_sz_dest_data;i++)
00491     if(_dest_data[i]<=otherC->getData()[i])
00492       {
00493         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
00494         return ret;
00495       }
00496   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
00497   return ret;
00498 }
00499 
00500 Value *ValueDoubleExpr::lowerThan(const Value *other) const throw(INTERP_KERNEL::Exception)
00501 {
00502   const ValueDoubleExpr *otherC=static_cast<const ValueDoubleExpr *>(other);
00503   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00504   for(int i=0;i<_sz_dest_data;i++)
00505     if(_dest_data[i]>=otherC->getData()[i])
00506       {
00507         std::fill(ret->getData(),ret->getData()+_sz_dest_data,-std::numeric_limits<double>::max());
00508         return ret;
00509       }
00510   std::fill(ret->getData(),ret->getData()+_sz_dest_data,std::numeric_limits<double>::max());
00511   return ret;
00512 }
00513 
00514 Value *ValueDoubleExpr::ifFunc(const Value *the, const Value *els) const throw(INTERP_KERNEL::Exception)
00515 {
00516   const ValueDoubleExpr *theC=static_cast<const ValueDoubleExpr *>(the);
00517   const ValueDoubleExpr *elsC=static_cast<const ValueDoubleExpr *>(els);
00518   ValueDoubleExpr *ret=new ValueDoubleExpr(_sz_dest_data,_src_data);
00519   bool okmax=true;
00520   bool okmin=true;
00521   for(int i=0;i<_sz_dest_data && (okmax || okmin);i++)
00522     {
00523       okmax=_dest_data[i]==std::numeric_limits<double>::max();
00524       okmin=_dest_data[i]==-std::numeric_limits<double>::max();
00525     }
00526   if(okmax || okmin)
00527     {
00528       if(okmax)
00529         std::copy(theC->getData(),theC->getData()+_sz_dest_data,ret->getData());
00530       else
00531         std::copy(elsC->getData(),elsC->getData()+_sz_dest_data,ret->getData());
00532       return ret;
00533     }
00534   else
00535     {
00536       throw INTERP_KERNEL::Exception("ValueDoubleExpr::ifFunc : first parameter of ternary func is NOT a consequence of a boolean op !");
00537     }
00538 }