1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay (CEA/DEN)
21 #include "InterpKernelUnit.hxx"
22 #include "InterpKernelExprParser.hxx"
29 using namespace INTERP_KERNEL;
31 UnitDataBase UnitDataBase::_uniqueMapForExpr;
33 static const char InterpKernelMuAscii[2]={-0x4B,0x0};
35 static const char InterpKernelMuUnicode[3]={-0x3E,-0x4B,0x0};
37 const char *UnitDataBase::PREF_POW10[NB_OF_PREF_POW10]={"y","z","a","f","p","n",InterpKernelMuAscii,InterpKernelMuUnicode,"u","m","c","d",
38 "da","h","k","M","G","T","P","E","Z","Y"};
40 const double UnitDataBase::POW10[NB_OF_PREF_POW10]={1e-24,1e-21,1e-18,1e-15,1e-12,1e-9,1e-6,1e-6,1e-6,1e-3,1e-2,1e-1,
41 1e1,1e2,1e3,1e6,1e9,1e12,1e15,1e18,1e21,1e24};
43 static const char InterpKernelDegreeCAscii[3]={-0x50,0x43,0x0};
45 static const char InterpKernelDegreeCUnicode[4]={-0x3E,-0x50,0x43,0x0};
47 static const char InterpKernelDegreeCUnicodeWin[3]={-0x08,0x43,0x0};
49 const char *UnitDataBase::UNITS_RECOGN[NB_OF_UNITS_RECOGN]={"g","m","s","A","K",
50 "W","J","Hz","V","h","min","t","N","dyn",
51 "eV","Pa","atm","bar",InterpKernelDegreeCAscii,"C","ohm","F","S",
52 "T","H","P","St",InterpKernelDegreeCUnicode,InterpKernelDegreeCUnicodeWin};
54 const short UnitDataBase::PROJ_IN_BASE[NB_OF_UNITS_RECOGN][SIZE_OF_UNIT_BASE]=
74 {0,0,0,0,1},//degree C
83 {0,0,0,0,1},//degree C
87 const double UnitDataBase::MUL_COEFF[NB_OF_UNITS_RECOGN]=
89 1000.,1000.,1.,1000.,3600.,3600.,1e6,1000.,1e-2,
90 1.60217733e-16,1000.,1.01325e8,1e8,1.,1.,1000.,1e-3,
91 1000.,1000.,100.,1.,1.,1.,1.};
93 const double UnitDataBase::ADD_COEFF[NB_OF_UNITS_RECOGN]=
94 { 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 273.15, 0., 0., 0., 0., 0., 0., 0., 0., 273.15 ,273.15};
96 UnitDataBase::UnitDataBase()
98 for(int i=0;i<NB_OF_PREF_POW10;i++)
99 _prefix_pow_10[PREF_POW10[i]]=POW10[i];
100 for(int i=0;i<NB_OF_UNITS_RECOGN;i++)
102 _units_semantic[UNITS_RECOGN[i]]=PROJ_IN_BASE[i];
103 _units_mul[UNITS_RECOGN[i]]=MUL_COEFF[i];
104 _units_add[UNITS_RECOGN[i]]=ADD_COEFF[i];
108 const short *UnitDataBase::getInfoForUnit(const std::string& unit,
109 double& addFact, double& mFact) const throw(INTERP_KERNEL::Exception)
111 std::size_t lgth=unit.length();
112 std::string work,work2;
114 for(std::size_t i=0;i<lgth && !ret;i++)
117 std::map<std::string,const short *>::const_iterator iter=_units_semantic.find(work);
118 if(iter!=_units_semantic.end())
121 std::map<std::string,double>::const_iterator iter2=_units_add.find(work);
122 addFact=(*iter2).second;
123 std::map<std::string,double>::const_iterator iter3=_units_mul.find(work);
124 mFact=(*iter3).second;
125 work2=unit.substr(0,i);
130 std::ostringstream os;
131 os << "Unit : " << unit << " not recognized !";
132 throw INTERP_KERNEL::Exception(os.str().c_str());
136 std::map<std::string,double>::const_iterator iter4=_prefix_pow_10.find(work2);
137 if(iter4==_prefix_pow_10.end())
139 std::ostringstream os;
140 os << "Unit : " << unit << " not fully recognized : \"" << work << "\" detected as core unit and \"";
141 os << work2 << "\" not recognized prefix !";
142 throw INTERP_KERNEL::Exception(os.str().c_str());
145 mFact*=(*iter4).second;
150 DecompositionInUnitBase::DecompositionInUnitBase():_add_to_base(0.),_mult_fact_to_base(1.)
159 void DecompositionInUnitBase::setInfo(const short *vals, double addFact, double mFact)
161 _add_to_base=addFact;
162 _mult_fact_to_base=mFact;
170 bool DecompositionInUnitBase::operator==(const DecompositionInUnitBase& other) const
172 return _value[0]==other._value[0] && _value[1]==other._value[1] && _value[2]==other._value[2] && _value[3]==other._value[3] && _value[4]==other._value[4];
175 void DecompositionInUnitBase::getTranslationParams(const DecompositionInUnitBase& other, double& mul, double& add) const
179 mul=_mult_fact_to_base/other._mult_fact_to_base;
180 add=_add_to_base/other._mult_fact_to_base-other._add_to_base;
184 mul=std::numeric_limits<double>::max();
185 add=std::numeric_limits<double>::max();
189 bool DecompositionInUnitBase::isEqual(short mass, short lgth, short time, short intensity, short temp, double add, double mult)
191 bool ret1=mass==_value[0];
192 bool ret2=lgth==_value[1];
193 bool ret3=time==_value[2];
194 bool ret4=intensity==_value[3];
195 bool ret5=temp==_value[4];
196 bool ret6=areDoubleEquals(add,_add_to_base);
197 bool ret7=areDoubleEquals(mult,_mult_fact_to_base);
198 return ret1 && ret2 && ret3 && ret4 && ret5 && ret6 && ret7;
201 void DecompositionInUnitBase::negate()
203 _mult_fact_to_base=-_mult_fact_to_base;
206 bool DecompositionInUnitBase::isAdimensional() const
208 return _value[0]==0 && _value[1]==0 && _value[2]==0 && _value[3]==0 && _value[4]==0;
211 bool DecompositionInUnitBase::isUnitary() const
213 return areDoubleEquals(_add_to_base,0.) && areDoubleEquals(_mult_fact_to_base,1.);
216 void DecompositionInUnitBase::tryToConvertInUnit(double val) throw(INTERP_KERNEL::Exception)
219 if((val-(double)valI)!=0.)
221 std::ostringstream os;
222 os << "Double value " << val << " can't be considered as integer. Not admitable for units !";
223 throw INTERP_KERNEL::Exception(os.str().c_str());
231 _mult_fact_to_base=valI;
234 DecompositionInUnitBase &DecompositionInUnitBase::operator*(const DecompositionInUnitBase& other)
236 _value[0]+=other._value[0]; _value[1]+=other._value[1]; _value[2]+=other._value[2]; _value[3]+=other._value[3]; _value[4]+=other._value[4];
237 _mult_fact_to_base*=other._mult_fact_to_base;
242 DecompositionInUnitBase &DecompositionInUnitBase::operator/(const DecompositionInUnitBase& other)
244 _value[0]-=other._value[0]; _value[1]-=other._value[1]; _value[2]-=other._value[2]; _value[3]-=other._value[3]; _value[4]-=other._value[4];
245 _mult_fact_to_base/=other._mult_fact_to_base;
250 DecompositionInUnitBase &DecompositionInUnitBase::operator^(const DecompositionInUnitBase& other) throw(INTERP_KERNEL::Exception)
252 if(!other.isAdimensional())
253 throw INTERP_KERNEL::Exception("Trying to execute operator ^ with a second member not adimensionnal");
254 int exp=couldItBeConsideredAsInt(other._mult_fact_to_base);
255 _value[0]*=exp; _value[1]*=exp; _value[2]*=exp; _value[3]*=exp; _value[4]*=exp;
256 _mult_fact_to_base=powInt(_mult_fact_to_base,exp);
261 void DecompositionInUnitBase::dealWithAddFactor(const DecompositionInUnitBase& other)
263 if(!areDoubleEquals(_add_to_base,0.))
264 if(other.isAdimensional())
265 if(areDoubleEquals(other._mult_fact_to_base,1.))
267 if(!other.areDoubleEquals(_add_to_base,0.))
269 if(areDoubleEquals(_mult_fact_to_base,1.))
274 double DecompositionInUnitBase::powInt(double val, int exp)
280 for(int i=0;i<exp;i++)
285 for(int i=0;i<tmp;i++)
291 bool DecompositionInUnitBase::areDoubleEquals(double a, double b)
295 double ref=std::max(a,b);
296 return fabs((a-b)/ref)<1e-7;
299 int DecompositionInUnitBase::couldItBeConsideredAsInt(double val) throw(INTERP_KERNEL::Exception)
302 double valT=(double) ret;
307 std::ostringstream stream; stream << "Invalid double number " << std::setprecision(16) << val << " can's be considered for ^ operation on unit.";
308 throw INTERP_KERNEL::Exception(stream.str().c_str());
312 Unit::Unit(const char *reprC, bool tryToInterp):_coarse_repr(reprC),
313 _is_interpreted(false),
314 _is_interpretation_ok(false)
320 Unit::Unit(const char *reprFortran, int sizeOfRepr, bool tryToInterp):_coarse_repr(ExprParser::buildStringFromFortran(reprFortran,sizeOfRepr)),
321 _is_interpreted(false),
322 _is_interpretation_ok(false)
326 void Unit::tryToInterprate() const
330 _is_interpreted=true;
331 _is_interpretation_ok=false;
334 ExprParser expr(_coarse_repr.c_str());
336 _decomp_in_base=expr.evaluateUnit();
337 _is_interpretation_ok=true;
339 catch(INTERP_KERNEL::Exception&) { }
343 bool Unit::isInterpretationOK() const
345 return _is_interpretation_ok;
348 bool Unit::isCompatibleWith(const Unit& other) const
351 other.tryToInterprate();
352 if(_is_interpretation_ok && other._is_interpretation_ok)
353 return _decomp_in_base==other._decomp_in_base;
358 double Unit::convert(const Unit& target, double sourceVal) const
360 if(isCompatibleWith(target))
363 _decomp_in_base.getTranslationParams(target._decomp_in_base,mult,add);
364 return mult*sourceVal+add;
367 return std::numeric_limits<double>::max();
370 std::string Unit::getCoarseRepr() const