26 #ifndef ANTIOCH_UNITS_H
27 #define ANTIOCH_UNITS_H
110 template <
typename T =
double>
115 Units(
const std::string &sym,
const std::string &na,
116 const T &conva,
const T &convb,
117 int mi,
int kgi=0,
int si=0,
int Ai=0,
int Ki=0,
int moli=0,
int cdi=0,
int radi=0);
119 Units(
const std::string &sym,
const std::string &na=
"");
121 Units(
const std::string & sym,
const Converter<T> &conv,
const std::string &na=
"");
132 void print(std::ostream &os = std::cout)
const;
269 void set_unit(
const std::string &sym, std::string na);
393 void showAll(std::ostream &out = std::cout);
488 bool is_number(
char c)
const {
return ((
int)c <= 57 && (
int)c >= 48);}
547 const std::string
add_SI(
int pow,std::string SIsymb)
const;
593 const T &conva,
const T &convb,
594 int mi,
int kgi,
int si,
int Ai,
int Ki,
int moli,
int cdi,
int radi):
598 power(mi,kgi,si,Ai,Ki,moli,cdi,radi)
622 template <
typename T>
625 if(symbol.empty())
return;
626 develop_symbol(symbol);
628 std::string tmp(
""),symboltmp(symbol);
629 int signe(1),istart(0);
631 while(symboltmp != contracted_symbol(symboltmp))symboltmp = contracted_symbol(symboltmp);
632 if(symboltmp.empty())
return;
634 if(symboltmp[0] ==
'/')
639 for(
unsigned int i = istart ; i < symboltmp.size() ; i++)
641 if(symboltmp[i] ==
'.')
643 if(!parse_single_unit(signe,tmp,doConv))
645 antioch_unit_error(
"In symbol " + symboltmp +
", unit \"" + tmp +
"\" does not ring a bell");
650 }
else if(symboltmp[i] ==
'/')
652 if(!parse_single_unit(signe,tmp,doConv))
654 antioch_unit_error(
"In symbol " + symboltmp +
", unit \"" + tmp +
"\" does not ring a bell");
664 if(!parse_single_unit(signe,tmp,doConv))
665 antioch_unit_error(
"In symbol " + symboltmp +
", unit \"" + tmp +
"\" does not ring a bell");
668 template <
typename T>
671 if(subsymb ==
"no unit" || subsymb ==
"No unit" || subsymb ==
"NO UNIT")
676 if(subsymb.find(
"(") == std::string::npos)
return;
684 unsigned int no(0),nc(0);
685 unsigned int po(0),pc(subsymb.size() - 1);
686 for(
unsigned int cc = 0; cc < subsymb.size(); cc++)
688 if(subsymb[cc] ==
'(')
691 if(po == 0 && cc != 0)po = cc;
693 if(subsymb[cc] ==
')')
707 subsymb.erase(po - 1 + off,3 - off);
710 std::string insideStr = subsymb.substr(po + 1,pc - po - 1);
711 develop_symbol(insideStr);
712 if(po != 0)
if(subsymb[po - 1] ==
'/')reverse_power_symbol(insideStr);
713 subsymb.replace(po,pc - po + 1,insideStr);
719 pc = subsymb.size() - 1;
725 if(subsymb[0] ==
'/')
728 po = subsymb.find(
".");
729 if(po > subsymb.find(
"/"))po = subsymb.find(
"/");
730 std::string curUnit = subsymb.substr(0,po);
731 int nc(0),
pow = - parse_power(curUnit,nc);
734 std::ostringstream np;
736 if(po < subsymb.size())
738 subsymb.replace(po - nc,nc,np.str());
745 subsymb.erase(po - nc,nc);
747 }
else if(subsymb[0] ==
'.')
754 template <
typename T>
757 if(is_homogeneous(target))
770 return factor_to_some_unit(
Units<T>(target));
773 template <
typename T>
776 if(is_homogeneous(target))
787 template <
typename T>
794 if(iUnit == -1 && unit.size() > 1)
796 std::string pre = unit.substr(0,1);
797 std::string un = unit.substr(1,std::string::npos);
800 if(iPre == -1 && iUnit == -1 && unit.size() > 2)
802 pre = unit.substr(0,2);
803 un = unit.substr(2,std::string::npos);
811 template <
typename T>
814 int iUnit = -1, nc = 0;
815 int ipower = parse_power(unit,nc);
818 unit = unit.substr(0,unit.length()-nc);
820 parse_prefix_unit(iUnit,iPre,unit);
822 if(iUnit == -1)
return false;
827 unit !=
"kg")pre *= 1e-3L;
829 power += (powerTmp * signe * ipower);
833 toSI +=
raise(convTmp,signe * ipower);
839 template <
typename T>
844 if(unit.empty())
return -1;
861 template <
typename T>
864 int ip = 1, loc = unit.length();
865 char c = unit[loc-1];
873 if(unit[loc-1] ==
'-'){
878 std::string power = unit.substr(loc,std::string::npos);
891 template <
typename T>
897 template <
typename T>
902 return (!this->is_united());
906 return is_homogeneous(rhs);
911 template <
typename T>
914 if(SIask ==
"m")
return power.get_m();
915 if(SIask ==
"kg")
return power.get_kg();
916 if(SIask ==
"s")
return power.get_s();
917 if(SIask ==
"A")
return power.get_A();
918 if(SIask ==
"K")
return power.get_K();
919 if(SIask ==
"mol")
return power.get_mol();
920 if(SIask ==
"cd")
return power.get_cd();
921 if(SIask ==
"rad")
return power.get_rad();
928 template <
typename T>
934 if(power.get_m() != 0)SISymb += add_SI(power.get_m(),
"m");
936 if(power.get_kg() != 0)
938 if(!SISymb.empty())SISymb +=
".";
939 SISymb += add_SI(power.get_kg(),
"kg");
941 if(power.get_s() != 0)
943 if(!SISymb.empty())SISymb +=
".";
944 SISymb += add_SI(power.get_s(),
"s");
946 if(power.get_A() != 0)
948 if(!SISymb.empty())SISymb +=
".";
949 SISymb += add_SI(power.get_A(),
"A");
951 if(power.get_K() != 0)
953 if(!SISymb.empty())SISymb +=
".";
954 SISymb += add_SI(power.get_K(),
"K");
956 if(power.get_mol() != 0)
958 if(!SISymb.empty())SISymb +=
".";
959 SISymb += add_SI(power.get_mol(),
"mol");
961 if(power.get_cd() != 0)
963 if(!SISymb.empty())SISymb +=
".";
964 SISymb += add_SI(power.get_cd(),
"cd");
966 if(power.get_rad() != 0)
968 if(!SISymb.empty())SISymb +=
".";
969 SISymb += add_SI(power.get_rad(),
"rad");
976 template <
typename T>
981 if(pow == 0)
return out;
986 std::stringstream po;
995 template <
typename T>
998 std::string harmSymb(
"");
999 if(input.empty())input = symbol;
1001 std::vector<std::string> unitvec;
1002 std::vector<int> powervec;
1003 std::string curUnit(
""),interUnit(
".");
1005 for(
unsigned int i = 0; i < input.size(); i++)
1007 if(input[i] !=
'.' && input[i] !=
'/')curUnit += input[i];
1008 if(input[i] ==
'.' || input[i] ==
'/' || i == input.size() - 1 )
1010 if(curUnit.empty())
continue;
1013 int iUnit(-1),iPre(-1);
1014 int curPower = parse_power(curUnit,nc);
1016 curUnit = curUnit.substr(0,curUnit.length() - nc);
1017 parse_prefix_unit(iUnit,iPre,curUnit);
1021 antioch_unit_error(
"The unit \"" + curUnit +
"\" is unknown. No harmonized symbol will be produced.");
1028 if(interUnit ==
"/")curPower *= -1;
1032 for(j = 0; j < unitvec.size(); j++)
1039 powervec[j] += curPower;
1043 if(j >= unitvec.size())
1045 unitvec.push_back(curUnit);
1046 powervec.push_back(curPower);
1048 interUnit = input[i];
1057 bool ism(
false),isl(
false);
1058 unsigned int herem(0),herel(0);
1059 for(
unsigned int i = 0; i < unitvec.size(); i++)
1061 if(unitvec[i] ==
"m")
1066 if(unitvec[i] ==
"l")
1074 powervec[herem] += 3 * powervec[herel];
1075 unitvec.erase(unitvec.begin() + herel);
1076 powervec.erase(powervec.begin() + herel);
1081 std::ostringstream outsym;
1083 for(
unsigned int i = 0; i < unitvec.size(); i++)
1085 if(powervec[i] == 0)
continue;
1091 }
else if(powervec[i] < 0)
1097 outsym << unitvec[i];
1098 if(powervec[i] != 1)outsym << powervec[i];
1102 harmSymb = outsym.str();
1107 template <
typename T>
1112 if(power.get_m() != 0)ndim++;
1113 if(power.get_kg() != 0)ndim++;
1114 if(power.get_s() != 0)ndim++;
1115 if(power.get_A() != 0)ndim++;
1116 if(power.get_K() != 0)ndim++;
1117 if(power.get_mol() != 0)ndim++;
1118 if(power.get_cd() != 0)ndim++;
1119 if(power.get_rad() != 0)ndim++;
1124 template <
typename T>
1127 if(this->n_dimension_of_units() == 0)
1129 std::string outStr(
"");
1139 return get_SI_symb();
1143 template <
typename T>
1150 fill_in_power(
true);
1153 template <
typename T>
1156 unsigned int curInter;
1157 curInter = subsymbol.find(
".");
1158 if(subsymbol.find(
"/") < curInter)curInter = subsymbol.find(
"/");
1159 while(curInter < subsymbol.size())
1161 (subsymbol[curInter] ==
'.')?
1162 subsymbol.replace(curInter,1,
"/"):
1163 subsymbol.replace(curInter,1,
".");
1165 unsigned int tmp = subsymbol.find(
".",curInter);
1166 if(subsymbol.find(
"/",curInter) < tmp)tmp = subsymbol.find(
"/",curInter);
1171 template <
typename T>
1174 if(n_dimension_of_units() == 0)
return;
1175 std::string curUnit(
"");
1176 std::string tmpSymbol = contracted_symbol();
1177 for(
unsigned int i = 0; i < tmpSymbol.size(); i++)
1179 if(tmpSymbol[i] !=
'.' && tmpSymbol[i] !=
'/')curUnit += tmpSymbol[i];
1180 if(tmpSymbol[i] ==
'.' || tmpSymbol[i] ==
'/' || i == tmpSymbol.size() - 1 )
1183 std::ostringstream po;
1184 int resultPower = get_integer_power(parse_power(curUnit,nc),r,key);
1185 if(resultPower == 0)
1191 std::string postr = po.str();
1192 if(resultPower == 1)postr =
"";
1195 (i != tmpSymbol.size() - 1)?tmpSymbol.replace(i - nc,nc,postr):
1196 tmpSymbol.replace(i - nc + 1,nc,postr);
1199 (i != tmpSymbol.size() - 1)?tmpSymbol.insert(i,postr):tmpSymbol.insert(i + 1,postr);
1209 template <
typename T>
1217 if(unit%r != 0)
return 0;
1221 std::cerr <<
"Key is not acceptable. This is a private method, there is a big problem..." << std::endl;
1229 template <
typename T>
1235 template <
typename T>
1241 template <
typename T>
1248 !this->is_number(c));
1251 template <
typename T>
1254 out <<
"Unit description:" << std::endl;
1255 out <<
"name: " << name << std::endl;
1256 out <<
"symbol: " << symbol << std::endl;
1257 out <<
"SI decomposition: " << power << std::endl;
1258 out <<
"SI converter: " << toSI << std::endl << std::endl;
1261 template <
typename T>
1264 if(
this == &rhs){
return *
this;}
1269 fill_in_power(
true);
1273 template <
typename T>
1294 template <
typename T>
1302 this->develop_symbol(symbol);
1309 template <
typename T>
1313 toSI = this->
raise(toSI,r);
1314 this->symbol_to_the_power(r,1);
1315 if(symbol ==
"failed")
1317 symbol = this->get_SI_symb();
1323 template <
typename T>
1327 this->symbol_to_the_power(r,-1);
1328 if(symbol ==
"failed")
1330 symbol = this->get_SI_symb();
1332 toSI = this->
raise(toSI,1./(T)r);
1338 template <
typename T>
1344 template <
typename T>
1350 template <
typename T>
1356 template <
typename T>
1362 template <
typename T>
1365 os << name <<
" (" << symbol <<
"), "
1367 << power << std::endl;
bool is_united() const
Test if the unit is non empty.
void set_unit(const std::string &sym)
Units setter, sets the unit to the given symbol and name.
void add(Units< T > *rhs)
Alternative call to Units& operator+=(const Units &)
void develop_symbol(std::string &subsymbol)
Supress the parenthesises.
const std::string get_SI_symb() const
Corresponding SI symbol getter.
const std::string manipulate_symbol(std::string input, bool contract) const
Root method for contracting or harmonizing the symbol.
Units< T > & operator=(const Units< T > &rhs)
Assignement operator.
const std::string get_symbol() const
String symbol getter.
Units< T > operator/(int r) const
Dividing operator by an integer, uses Units &operator/=(int)
const std::string get_SI_convenient_symb() const
Corresponding SI symbol getter.
int indexUnit(std::string unit) const
Scanner of knownUnits[], sends back the corresponding iUnit, -1 if not found.
Units< T > & operator*=(int r)
Multiplying operator by an integer.
int n_dimension_of_units() const
Number of dimensions of the unit in the SI basis.
Units< T > & operator/=(int r)
dividing operator by an integer
void root(int r)
Alternative method to Units& operator/=(int)
Converter< T > raise(const Converter< T > &tbm, int power) const
Raise to an integer power a Converter object.
void equalize(const Units< T > &rhs)
Alternative call to Units& operator=(const Units &)
void check_if_name(std::string &nameOut, const Units< T > &un) const
Fill the name if empty and name obvious.
void showAll(std::ostream &out=std::cout)
showAll().
void symbol_to_the_power(int r, const int &key)
Rewrite the symbol to put it at a given power.
void set_symbol(const std::string &symb)
Symbol setter.
void set_SI_converter(const Converter< T > &conv)
Coefficient setter.
bool operator!=(const Units< T > &rhs) const
Comparison operator, not equal is not "equal".
void reverse_power_symbol(std::string &subsymbol)
Treat part of symbol depending on parenthesises.
Units< T > operator+(const Units< T > &rhs) const
Adding operator, uses Units &operator+=(const Units&)
void add(std::string unit)
Alternative call to Units& operator+=(const Units &)
friend std::ostream & operator<<(std::ostream &os, const Units< T > &unit)
Formatted print.
const P geta() const
Multiplicative factor getter.
void set_unit(const std::string &sym, std::string na)
Units setter, sets the unit to the given symbol and name.
int get_integer_power(int unit, int r, const int &key)
Multiply or divide a power.
Antioch::enable_if_c< Antioch::is_valarray< T >::value, typename Antioch::state_type< T >::type >::type pow(const T &in, const T2 &n)
void init_clone(T &output, const T &example)
Converter< T > toSI
A Converter for the coefficient.
bool is_in_symb(char c) const
Small method that checks if the symbol is within a unit std::string.
T get_SI_factor() const
Multiplicative coefficient getter.
#define antioch_unit_error(description)
bool operator==(const Units< T > &rhs) const
Comparison operator.
Units< T > & operator-=(const Units< T > &rhs)
Substracting operator.
void clear()
Set all the powers to zeros.
T translator_to_some_unit(const Units< T > &target) const
Calculates the translator to any given unit, see factor_to_some_unit(const Units&) for the equations...
T factor_to_some_unit(const Units< T > &target) const
Calculates the factor to any given unit.
void print(std::ostream &os=std::cout) const
Formatted print.
void parse_prefix_unit(int &iUnit, int &iPre, const std::string &unit) const
Unit parser, parse a std::string of type Prefixes[] knownUnits[].
bool is_number(char c) const
Small method to check if a character is a numerical.
T get_SI_translator() const
Translationnal coefficient getter.
const Converter< T > get_SI_coef() const
Coefficient getter.
InSI power
An InSI for the power vector.
void set_power_to_SI(const InSI &mat)
Power std::vector setter.
const std::string add_SI(int pow, std::string SIsymb) const
Small method to add the SI symbol and power to a std::string.
void set_name(const std::string &na)
Name setter.
Seven integers to characterize the power vector.
void add(const Units< T > &rhs)
Alternative call to Units& operator+=(const Units &)
Units< T > operator-(const Units< T > &rhs) const
Substracting operator, uses Units &operator-=(const Units&)
const std::string contracted_symbol(const std::string &input="") const
Contract the symbol when possible.
const std::string harmonized_symbol(const std::string &input="") const
Simplify the symbol when possible.
bool parse_single_unit(int signe, std::string unit, bool doConv)
Calculates the corresponding coefficient and power of the given unit.
~Units()
Default destructor.
const UnitBaseConstant::SIPrefixeStore< long double > known_prefixes()
void clear()
Clear the unit.
int parse_power(std::string unit, int &nc) const
brief parser for std::string of type "some_unit power_associated".
bool empty() const
Check if empty (all values to zero)
const InSI get_power() const
Power std::vector getter.
std::string symbol
Strings for the symbol.
const UnitBaseConstant::UnitBaseStore< long double > known_units()
Class to deal with the conversion between units.
bool is_homogeneous(const Units< T > &rhs) const
Homogenity testing with another Units.
const P getb() const
Translationnal factor getter.
The parameters are reduced parameters.
std::string name
Strings for the name.
void equalize(Units< T > *rhs)
Alternative call to Units& operator=(const Units &)
Units< T > & operator+=(const Units< T > &rhs)
Adding operator.
void substract(Units< T > *rhs)
Alternative call to Units& operator-=(const Units &)
Units< T > operator*(int r) const
Multiplying operator by an integer, uses Units &operator*=(int)
Units()
Default constructor.
int get_SI_power(const std::string &SIask) const
Power of the asked SI unit.
const std::string get_name() const
String name getter.
void substract(const std::string &unit)
Alternative call to Units& operator-=(const Units &)
void fill_in_power(bool doConv)
This method fills the power vector and will calculate the coefficient if the bool doConv is set to tr...
void substract(const Units< T > &rhs)
Alternative call to Units& operator-=(const Units &)
T translator_to_some_unit(const std::string &target) const
Calculates the translator to any given unit, uses translator_to_some_unit(const Units&).
void equalize(std::string unit)
Alternative call to Units& operator=(const Units &)