antioch-0.4.0
units.h
Go to the documentation of this file.
1 //-----------------------------------------------------------------------bl-
2 //--------------------------------------------------------------------------
3 //
4 // Antioch - A Gas Dynamics Thermochemistry Library
5 //
6 // Copyright (C) 2014-2016 Paul T. Bauman, Benjamin S. Kirk,
7 // Sylvain Plessis, Roy H. Stonger
8 //
9 // Copyright (C) 2013 The PECOS Development Team
10 //
11 // This library is free software; you can redistribute it and/or
12 // modify it under the terms of the Version 2.1 GNU Lesser General
13 // Public License as published by the Free Software Foundation.
14 //
15 // This library is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 // Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public
21 // License along with this library; if not, write to the Free Software
22 // Foundation, Inc. 51 Franklin Street, Fifth Floor,
23 // Boston, MA 02110-1301 USA
24 //
25 //-----------------------------------------------------------------------el-
26 #ifndef ANTIOCH_UNITS_H
27 #define ANTIOCH_UNITS_H
28 
29 //Antioch
32 #include "antioch/siprefix.h"
33 #include "antioch/insi.h"
34 #include "antioch/converter.h"
35 #include "antioch/unit_defs.h"
36 
37 //C++
38 #include <vector>
39 #include <cmath>
40 #include <sstream>
41 #include <iomanip>
42 
43 namespace Antioch{
44 
110 template <typename T = double>
111 class Units{
112  public:
113 
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);//constructors for known Units
119  Units(const std::string &sym, const std::string &na=""); //constructors when automatic conversion
121  Units(const std::string & sym, const Converter<T> &conv, const std::string &na="");//constructor for given conversion
123  Units(){}
124 
126  ~Units(){}
127 
129 
132  void print(std::ostream &os = std::cout) const;
133 
135 
138  friend std::ostream& operator<<( std::ostream& os,
139  const Units<T>& unit )
140  {
141  unit.print(os);
142  return os;
143  }
144 
145 
151  bool operator== (const Units<T> &rhs) const;
153  bool operator!= (const Units<T> &rhs) const {return !(*this == rhs);}
159  Units<T> &operator= (const Units<T> & rhs);
175  Units<T> &operator+=(const Units<T> & rhs);
191  Units<T> &operator-=(const Units<T> & rhs);
193  Units<T> operator+ (const Units<T> & rhs) const;
195  Units<T> operator- (const Units<T> & rhs) const;
210  Units<T> &operator*=(int r);
212  Units<T> operator* (int r) const;
227  Units<T> &operator/=(int r);
229  Units<T> operator/ (int r) const;
230 
232  void equalize(const Units<T> &rhs) {*this = rhs;}
234  void equalize(Units<T> *rhs) {*this = *rhs;}
246  void equalize(std::string unit) {*this = Units<T>(unit);}
248  void add(const Units<T> &rhs) {*this += rhs;}
250  void add(Units<T> *rhs) {*this += *rhs;}
255  void add(std::string unit) {*this += Units<T>(unit);}
257  void substract(const Units<T> &rhs) {*this -= rhs;}
259  void substract(Units<T> *rhs) {*this -= *rhs;}
264  void substract(const std::string &unit) {*this -= Units<T>(unit);}
266  void root(int r) {*this /= r;}
267 
269  void set_unit(const std::string &sym, std::string na);
271  void set_unit(const std::string &sym) {set_unit(sym,"");}
273  void set_name(const std::string &na) {name = na;}
275  void set_symbol(const std::string &symb) {symbol = symb;}
279  void set_power_to_SI(const InSI &mat) {power = mat;}
280 
288  bool is_homogeneous(const Units<T> &rhs) const;
296  bool is_homogeneous(std::string target) const;
298  bool is_united() const {return !power.empty();}
299 
300 
319  T factor_to_some_unit(const Units<T> & target) const;
321  T factor_to_some_unit(const std::string &target) const;
323  T translator_to_some_unit(const Units<T> & target) const;
325  T translator_to_some_unit(const std::string &target) const {return translator_to_some_unit(Units<T>(target));}
326 
328  const std::string get_name() const {return name;}
330  const std::string get_symbol() const {return symbol;}
332  const Converter<T> get_SI_coef() const {return toSI;}
334  T get_SI_factor() const {return toSI.geta();}
336  T get_SI_translator() const {return toSI.getb();}
338  const InSI get_power() const {return power;}
344  const std::string get_SI_symb() const;
350  int get_SI_power(const std::string &SIask) const;
362  const std::string get_SI_convenient_symb() const;
381  const std::string harmonized_symbol(const std::string &input = "") const {return manipulate_symbol(input,false);}
387  const std::string contracted_symbol(const std::string &input = "") const {return manipulate_symbol(input,true);}
388 
390  void clear(){symbol.clear();name.clear();toSI.clear();power.clear();}
391 
393  void showAll(std::ostream &out = std::cout);
394 
395  private:
396 
401  const std::string manipulate_symbol(std::string input, bool contract) const;
402 
403 
413  void fill_in_power(bool doConv);
451  bool parse_single_unit(int signe, std::string unit, bool doConv);
472  void parse_prefix_unit(int &iUnit,int &iPre, const std::string &unit) const;
474  int indexUnit(std::string unit) const;
481  int parse_power(std::string unit, int &nc) const;
488  bool is_number(char c) const {return ((int)c <= 57 && (int)c >= 48);} //ascii table
489 
502  Converter<T> raise(const Converter<T> &tbm,int power) const;
508  Converter<T> raise(const Converter<T> &tbm,double power) const;
524  void develop_symbol(std::string &subsymbol);
532  void reverse_power_symbol(std::string &subsymbol);
539  bool is_in_symb(char c) const;
541  int n_dimension_of_units() const;
547  const std::string add_SI(int pow,std::string SIsymb) const;
555  void symbol_to_the_power(int r, const int &key);
568  int get_integer_power(int unit,int r, const int &key);
576  void check_if_name(std::string &nameOut, const Units<T> &un) const;
577 
579  std::string symbol;
581  std::string name;
586 
587 };
588 
589 
590 template<typename T>
591 inline
592 Units<T>::Units(const std::string &sym, const std::string &na,
593  const T &conva, const T &convb,
594  int mi,int kgi, int si, int Ai, int Ki, int moli, int cdi, int radi): //fully descriptive constructor
595  symbol(sym),
596  name(na),
597  toSI(conva,convb),
598  power(mi,kgi,si,Ai,Ki,moli,cdi,radi)
599 {
601 }
602 
603 template<typename T>
604 inline
605 Units<T>::Units(const std::string &sym, const std::string &na): //constructors when automatic conversion
606  symbol(sym),
607  name(na)
608 {
609  fill_in_power(true);
610 }
611 
612 template<typename T>
613 inline
614 Units<T>::Units(const std::string &sym, const Converter<T> &conv, const std::string &na)://constructor for given conversion
615  symbol(sym),
616  name(na),
617  toSI(conv)
618 {
619  fill_in_power(false);
620 }
621 
622 template <typename T>
623 void Units<T>::fill_in_power(bool doConv)
624 {
625  if(symbol.empty())return; // no unity
626  develop_symbol(symbol);
627 
628  std::string tmp(""),symboltmp(symbol);
629  int signe(1),istart(0);
630 
631  while(symboltmp != contracted_symbol(symboltmp))symboltmp = contracted_symbol(symboltmp);
632  if(symboltmp.empty())return; // no unity
633 
634  if(symboltmp[0] == '/')
635  {
636  signe = -1;
637  istart = 1;
638  }
639  for(unsigned int i = istart ; i < symboltmp.size() ; i++)
640  {
641  if(symboltmp[i] == '.')
642  {
643  if(!parse_single_unit(signe,tmp,doConv))
644  {
645  antioch_unit_error("In symbol " + symboltmp + ", unit \"" + tmp + "\" does not ring a bell");
646  break;
647  }
648  signe = 1;
649  tmp.clear();
650  }else if(symboltmp[i] == '/')
651  {
652  if(!parse_single_unit(signe,tmp,doConv))
653  {
654  antioch_unit_error("In symbol " + symboltmp + ", unit \"" + tmp + "\" does not ring a bell");
655  break;
656  }
657  signe = -1;
658  tmp.clear();
659  }else
660  {
661  tmp += symboltmp[i];
662  }
663  }
664  if(!parse_single_unit(signe,tmp,doConv))
665  antioch_unit_error("In symbol " + symboltmp + ", unit \"" + tmp + "\" does not ring a bell");
666 }
667 
668 template <typename T>
669 void Units<T>::develop_symbol(std::string &subsymb)
670 {
671  if(subsymb == "no unit" || subsymb == "No unit" || subsymb == "NO UNIT")
672  {
673  subsymb.clear();
674  return;
675  }
676  if(subsymb.find("(") == std::string::npos)return;
677 
678 //model is a serie ().()/()..., we find it
679 // we count the opening parenthesises (no) and
680 // the closing parenthesises (nc). We need to
681 // keep track of the position of opening (po)
682 // and closing (pc) parenthesises. We have a pair
683 // when no == nc.
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++)
687  {
688  if(subsymb[cc] == '(')
689  {
690  no++;
691  if(po == 0 && cc != 0)po = cc;
692  }
693  if(subsymb[cc] == ')')
694  {
695  nc++;
696  pc = cc;
697  }
698  if(no == 0)continue;
699 
700  if(no == nc)//found a pair
701  {
702  //develop it
703  if(pc == po + 1)
704  {
705  unsigned int off(0);
706  if(po == 0)off = 1;//if ( is the first character or not
707  subsymb.erase(po - 1 + off,3 - off);//if yes, suppress '()', if not suppress '.()' or '/()'
708  }else
709  {
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);
714  }
715  //reset the system
716  no = 0;
717  nc = 0;
718  po = 0;
719  pc = subsymb.size() - 1;
720  cc -= 2;
721  }
722  }
723 
724 //if first character is a power determinant ('/' or '.')
725  if(subsymb[0] == '/') //we change only the first atomic unit
726  {
727  subsymb.erase(0,1);
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); //power
732  if(pow != 1)
733  {
734  std::ostringstream np;
735  np << pow;
736  if(po < subsymb.size())
737  {
738  subsymb.replace(po - nc,nc,np.str());
739  }else
740  {
741  subsymb += np.str();
742  }
743  }else
744  {
745  subsymb.erase(po - nc,nc);
746  }
747  }else if(subsymb[0] == '.')
748  {
749  subsymb.erase(0,1);
750  }
751 
752 }
753 
754 template <typename T>
756 {
757  if(is_homogeneous(target))
758  {
759  return get_SI_factor()/target.get_SI_factor();
760  }else
761  {
762  antioch_unit_error("Units are not homogeneous:\n\"" + symbol + "\" and \"" + target.get_symbol() + "\".");
763  return -1.;
764  }
765 }
766 
767 template<typename T>
768 T Units<T>::factor_to_some_unit(const std::string &target) const
769 {
770  return factor_to_some_unit(Units<T>(target));
771 }
772 
773 template <typename T>
775 {
776  if(is_homogeneous(target))
777  {
778  return ((this->get_SI_translator() - target.get_SI_translator())/target.get_SI_factor());
779  }
780  else
781  {
782  antioch_unit_error("Units are not homogeneous.");
783  return -1.;
784  }
785 }
786 
787 template <typename T>
788 void Units<T>::parse_prefix_unit(int &iUnit,int &iPre,const std::string& unit) const
789 {
790  iPre = -1;
791 
792  iUnit = UnitBaseStorage::known_units().stored_index(unit);
793 //prefix, if exists, is one or two character
794  if(iUnit == -1 && unit.size() > 1)
795  {
796  std::string pre = unit.substr(0,1);
797  std::string un = unit.substr(1,std::string::npos);
798  iPre = UnitBaseStorage::known_prefixes().stored_index(pre);
799  iUnit = UnitBaseStorage::known_units().stored_index(un);
800  if(iPre == -1 && iUnit == -1 && unit.size() > 2)
801  {
802  pre = unit.substr(0,2);
803  un = unit.substr(2,std::string::npos);
804  iPre = UnitBaseStorage::known_prefixes().stored_index(pre);
805  iUnit = UnitBaseStorage::known_units().stored_index(un);
806  }
807  }
808  return;
809 }
810 
811 template <typename T>
812 bool Units<T>::parse_single_unit(int signe,std::string unit,bool doConv)
813 {
814  int iUnit = -1, nc = 0;
815  int ipower = parse_power(unit,nc); // find power
816  int iPre = -1;
817 
818  unit = unit.substr(0,unit.length()-nc); //unit without power
819 
820  parse_prefix_unit(iUnit,iPre,unit);//find prefix and unit
821 
822  if(iUnit == -1)return false; //not found
823 
824  T pre = 1.L;
825  if(iPre != -1)pre = UnitBaseStorage::known_prefixes().stored(iPre).value<T>();
826  if(UnitBaseStorage::known_units().stored(iUnit).symbol() == "kg" &&
827  unit != "kg")pre *= 1e-3L; //rescale
828  InSI powerTmp = UnitBaseStorage::known_units().stored(iUnit).power_array();
829  power += (powerTmp * signe * ipower);
830  if(doConv)
831  {
832  Converter<T> convTmp = UnitBaseStorage::known_units().stored(iUnit).converter() * pre;
833  toSI += raise(convTmp,signe * ipower);
834  }
835 
836  return true;
837 }
838 
839 template <typename T>
840 int Units<T>::indexUnit(std::string unit) const
841 {
842  int iUnit;
843 
844  if(unit.empty())return -1;
845 
846  if(unit == "g")//special case to adapt SI
847  {
848  unit = "kg";
849  }
850  for (iUnit = 0; iUnit < UnitBaseStorage::known_units().n_known_units() ; iUnit++)
851  {
852  if(unit == UnitBaseStorage::known_units().stored(iUnit).symbol())break;
853  }
854 
855  if(iUnit >= UnitBaseStorage::known_units().n_known_units())iUnit=-1;
856 
857 
858  return iUnit;
859 }
860 
861 template <typename T>
862 int Units<T>::parse_power(std::string unit,int &nc) const
863 {
864  int ip = 1, loc = unit.length();
865  char c = unit[loc-1];
866  nc = 0;
867  while(is_number(c)){
868  nc++;
869  loc--;
870  c = unit[loc-1];
871  }
872 
873  if(unit[loc-1] == '-'){
874  loc--;
875  nc++;
876  }
877 
878  std::string power = unit.substr(loc,std::string::npos);
879  if(power.size() > 0)
880  {
881  std::stringstream p;
882  p << power;
883  p >> ip;
884  }
885 
886  if(ip == 0)antioch_unit_error("Invalid power found: " + unit);
887 
888  return ip;
889 }
890 
891 template <typename T>
892 bool Units<T>::is_homogeneous(const Units<T> &rhs) const
893 {
894  return (power == rhs.get_power());
895 }
896 
897 template <typename T>
898 bool Units<T>::is_homogeneous(std::string target) const
899 {
900  if(target.empty())
901  {
902  return (!this->is_united());
903  }else
904  {
905  Units<T> rhs(target);
906  return is_homogeneous(rhs);
907  }
908 
909 }
910 
911 template <typename T>
912 int Units<T>::get_SI_power(const std::string &SIask) const
913 {
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();
922 
923  antioch_unit_error(SIask + " is not a SI symbol");
924 
925  return 0;
926 }
927 
928 template <typename T>
929 std::string const Units<T>::get_SI_symb() const
930 {
931  std::string SISymb;
932  SISymb.clear();
933 
934  if(power.get_m() != 0)SISymb += add_SI(power.get_m(),"m");
935 
936  if(power.get_kg() != 0)
937  {
938  if(!SISymb.empty())SISymb += ".";
939  SISymb += add_SI(power.get_kg(),"kg");
940  }
941  if(power.get_s() != 0)
942  {
943  if(!SISymb.empty())SISymb += ".";
944  SISymb += add_SI(power.get_s(),"s");
945  }
946  if(power.get_A() != 0)
947  {
948  if(!SISymb.empty())SISymb += ".";
949  SISymb += add_SI(power.get_A(),"A");
950  }
951  if(power.get_K() != 0)
952  {
953  if(!SISymb.empty())SISymb += ".";
954  SISymb += add_SI(power.get_K(),"K");
955  }
956  if(power.get_mol() != 0)
957  {
958  if(!SISymb.empty())SISymb += ".";
959  SISymb += add_SI(power.get_mol(),"mol");
960  }
961  if(power.get_cd() != 0)
962  {
963  if(!SISymb.empty())SISymb += ".";
964  SISymb += add_SI(power.get_cd(),"cd");
965  }
966  if(power.get_rad() != 0)
967  {
968  if(!SISymb.empty())SISymb += ".";
969  SISymb += add_SI(power.get_rad(),"rad");
970  }
971 
972  return SISymb;
973 
974 }
975 
976 template <typename T>
977 const std::string Units<T>::add_SI(int pow,std::string symb) const
978 {
979  std::string out("");
980 
981  if(pow == 0)return out;
982 
983  out = symb;
984  if(pow != 1)
985  {
986  std::stringstream po;
987  po << pow;
988  out += po.str();
989  }
990 
991  return out;
992 
993 }
994 
995 template <typename T>
996 std::string const Units<T>::manipulate_symbol(std::string input, bool contract) const
997 {
998  std::string harmSymb("");
999  if(input.empty())input = symbol;
1000 
1001  std::vector<std::string> unitvec;
1002  std::vector<int> powervec;
1003  std::string curUnit(""),interUnit(".");//,strPower;
1004 
1005  for(unsigned int i = 0; i < input.size(); i++)
1006  {
1007  if(input[i] != '.' && input[i] != '/')curUnit += input[i];
1008  if(input[i] == '.' || input[i] == '/' || i == input.size() - 1 )
1009  {
1010  if(curUnit.empty())continue;
1011 //first, parsing the unit
1012  int nc(0);
1013  int iUnit(-1),iPre(-1);
1014  int curPower = parse_power(curUnit,nc); //power
1015 // strPower = curUnit.substr(curUnit.length() - nc,std::string::npos); //resulting power
1016  curUnit = curUnit.substr(0,curUnit.length() - nc); //resulting unit
1017  parse_prefix_unit(iUnit,iPre,curUnit);
1018  // unit is UnitBaseStorage::Prefixes[iPre].symbol() + UnitBaseStorage::knownUnits[iUnit].get_symbol() + strPower
1019  if(iUnit == -1)
1020  {
1021  antioch_unit_error("The unit \"" + curUnit + "\" is unknown. No harmonized symbol will be produced.");
1022  harmSymb.clear();
1023  return harmSymb;
1024  }
1025 //updating variables:
1026 // - curUnit is the unit (std::string)
1027 // - curPower is the power (int)
1028  if(interUnit == "/")curPower *= -1;
1029 
1030 // checking what we've got
1031  unsigned int j;
1032  for(j = 0; j < unitvec.size(); j++)
1033  {
1034  Units<T> tmp(unitvec[j]);
1035  bool same(tmp.get_symbol() == curUnit);//only contraction: strong condition
1036  if(!contract && !same)same = tmp.is_homogeneous(curUnit); //harmonizing: weak condition
1037  if(same)//if in there, update the power,
1038  {
1039  powervec[j] += curPower;
1040  break;
1041  }
1042  }
1043  if(j >= unitvec.size())//if not, add
1044  {
1045  unitvec.push_back(curUnit);
1046  powervec.push_back(curPower);
1047  }
1048  interUnit = input[i];
1049  curUnit.clear();
1050  }
1051  }
1052 
1053 //litre fix: only if harmonizing
1054 // if there is l AND m in the vector, all is converted to m.
1055  if(!contract)
1056  {
1057  bool ism(false),isl(false);
1058  unsigned int herem(0),herel(0);
1059  for(unsigned int i = 0; i < unitvec.size(); i++)
1060  {
1061  if(unitvec[i] == "m")
1062  {
1063  ism = true;
1064  herem = i;
1065  }
1066  if(unitvec[i] == "l")
1067  {
1068  isl = true;
1069  herel = i;
1070  }
1071  }
1072  if(ism && isl)
1073  {
1074  powervec[herem] += 3 * powervec[herel];
1075  unitvec.erase(unitvec.begin() + herel);
1076  powervec.erase(powervec.begin() + herel);
1077  }
1078  }
1079 //now writing harmsymb
1080 
1081  std::ostringstream outsym;
1082  int k(0);
1083  for(unsigned int i = 0; i < unitvec.size(); i++)
1084  {
1085  if(powervec[i] == 0)continue; //ignore deleted unit
1086  if(k != 0) // need a symbol, '.' or '/'
1087  {
1088  if(powervec[i] > 0) // '.'
1089  {
1090  outsym << ".";
1091  }else if(powervec[i] < 0) // '/' and reverse the power
1092  {
1093  outsym << "/";
1094  powervec[i] *= -1;
1095  }
1096  }
1097  outsym << unitvec[i];
1098  if(powervec[i] != 1)outsym << powervec[i];
1099  k++;
1100  }
1101 
1102  harmSymb = outsym.str();
1103 
1104  return harmSymb;
1105 }
1106 
1107 template <typename T>
1109 {
1110  int ndim(0);
1111 
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++;
1120 
1121  return ndim;
1122 }
1123 
1124 template <typename T>
1125 const std::string Units<T>::get_SI_convenient_symb() const
1126 {
1127  if(this->n_dimension_of_units() == 0)
1128  {
1129  std::string outStr("");
1130  return outStr;
1131  }else
1132  {
1133  for(int iUnit = 1; iUnit < UnitBaseStorage::known_units().n_known_units(); iUnit++)
1134  {
1135  if(is_homogeneous(UnitBaseStorage::known_units().stored(iUnit).symbol()) &&
1136  UnitBaseStorage::known_units().stored(iUnit).converter().geta() == 1. &&
1137  UnitBaseStorage::known_units().stored(iUnit).converter().getb() == 0.)return UnitBaseStorage::known_units().stored(iUnit).symbol();
1138  }
1139  return get_SI_symb();
1140  }
1141 }
1142 
1143 template <typename T>
1144 void Units<T>::set_unit(const std::string &sym, std::string na)
1145 {
1146  symbol = sym;
1147  name = na;
1148  toSI.clear();
1149  power.clear();
1150  fill_in_power(true);
1151 }
1152 
1153 template <typename T>
1154 void Units<T>::reverse_power_symbol(std::string &subsymbol)
1155 {
1156  unsigned int curInter;
1157  curInter = subsymbol.find(".");
1158  if(subsymbol.find("/") < curInter)curInter = subsymbol.find("/");
1159  while(curInter < subsymbol.size())
1160  {
1161  (subsymbol[curInter] == '.')?
1162  subsymbol.replace(curInter,1,"/"):
1163  subsymbol.replace(curInter,1,".");
1164  curInter++;
1165  unsigned int tmp = subsymbol.find(".",curInter);
1166  if(subsymbol.find("/",curInter) < tmp)tmp = subsymbol.find("/",curInter);
1167  curInter = tmp;
1168  }
1169 }
1170 
1171 template <typename T>
1172 void Units<T>::symbol_to_the_power(int r,const int &key)
1173 {
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++)
1178  {
1179  if(tmpSymbol[i] != '.' && tmpSymbol[i] != '/')curUnit += tmpSymbol[i];
1180  if(tmpSymbol[i] == '.' || tmpSymbol[i] == '/' || i == tmpSymbol.size() - 1 )
1181  {
1182  int nc(0);
1183  std::ostringstream po;
1184  int resultPower = get_integer_power(parse_power(curUnit,nc),r,key); //power
1185  if(resultPower == 0)
1186  {
1187  symbol = "failed";
1188  return;
1189  }
1190  po << resultPower;
1191  std::string postr = po.str();
1192  if(resultPower == 1)postr = "";
1193  if(nc != 0)
1194  {
1195  (i != tmpSymbol.size() - 1)?tmpSymbol.replace(i - nc,nc,postr):
1196  tmpSymbol.replace(i - nc + 1,nc,postr); //resulting unit
1197  }else
1198  {
1199  (i != tmpSymbol.size() - 1)?tmpSymbol.insert(i,postr):tmpSymbol.insert(i + 1,postr);
1200  }
1201  curUnit.clear();
1202  i += postr.size();
1203  }
1204  }
1205 
1206  symbol = tmpSymbol;
1207 }
1208 
1209 template <typename T>
1210 int Units<T>::get_integer_power(int unit,int r, const int &key)
1211 {
1212  if(key == 1)//multiplication
1213  {
1214  return unit * r;
1215  }else if(key == -1)//division
1216  {
1217  if(unit%r != 0)return 0;
1218  return unit / r;
1219  }else
1220  {
1221  std::cerr << "Key is not acceptable. This is a private method, there is a big problem..." << std::endl;
1222  antioch_error();
1223  return 0;
1224  }
1225 
1226 
1227 }
1228 
1229 template <typename T>
1230 Converter<T> Units<T>::raise(const Converter<T> &tbm,int power) const
1231 {
1232  return Converter<T>(std::pow(tbm.geta(),power),(power != 1)?0.:tbm.getb());
1233 }
1234 
1235 template <typename T>
1236 Converter<T> Units<T>::raise(const Converter<T> &tbm, double power) const
1237 {
1238  return Converter<T>(std::pow(tbm.geta(),power),(power != 1.)?0.:tbm.getb());
1239 }
1240 
1241 template <typename T>
1242 bool Units<T>::is_in_symb(char c) const
1243 {
1244 
1245  return (c != '/' &&
1246  c != '.' &&
1247  c != '-' &&
1248  !this->is_number(c));
1249 }
1250 
1251 template <typename T>
1252 void Units<T>::showAll(std::ostream &out)
1253 {
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;
1259 }
1260 
1261 template <typename T>
1263 {
1264  if(this == &rhs){return *this;}
1265  name = rhs.get_name();
1266  symbol = rhs.get_symbol();
1267  toSI.clear();
1268  power.clear();
1269  fill_in_power(true);
1270  return *this;
1271 }
1272 
1273 template <typename T>
1275 {
1276 
1277 // the name
1278  if(!rhs.get_name().empty())name += " " + rhs.get_name();
1279 
1280 // the symbol
1281  if(rhs.get_symbol().empty())return *this;
1282  if(!symbol.empty())
1283  {
1284  symbol += ".(" + rhs.get_symbol() + ")";
1285  }else
1286  {
1287  symbol = rhs.get_symbol();
1288  }
1289  toSI *= rhs.get_SI_coef();
1290  power += rhs.get_power();
1291  return *this;
1292 }
1293 
1294 template <typename T>
1296 {
1297  if(!rhs.get_name().empty())name += " / " + rhs.get_name();
1298  if(!rhs.get_symbol().empty())
1299  {
1300  symbol += "/(" + rhs.get_symbol() + ")";
1301  }
1302  this->develop_symbol(symbol);
1303  toSI /= rhs.get_SI_coef();
1304  power -= rhs.get_power();
1305 
1306  return *this;
1307 }
1308 
1309 template <typename T>
1311 {
1312  power *= r;
1313  toSI = this->raise(toSI,r);
1314  this->symbol_to_the_power(r,1);
1315  if(symbol == "failed")
1316  {
1317  symbol = this->get_SI_symb();
1318  }
1319 
1320  return *this;
1321 }
1322 
1323 template <typename T>
1325 {
1326  power /= r;//check consistency of root
1327  this->symbol_to_the_power(r,-1);
1328  if(symbol == "failed")
1329  {
1330  symbol = this->get_SI_symb();
1331  }
1332  toSI = this->raise(toSI,1./(T)r);
1333 
1334  return *this;
1335 }
1336 
1337 
1338 template <typename T>
1340 {
1341  return (Units<T>(*this) += rhs);
1342 }
1343 
1344 template <typename T>
1346 {
1347  return (Units<T>(*this) -= rhs);
1348 }
1349 
1350 template <typename T>
1352 {
1353  return (Units<T>(*this) *= r);
1354 }
1355 
1356 template <typename T>
1358 {
1359  return (Units<T>(*this) /= r);
1360 }
1361 
1362  template <typename T>
1363  void Units<T>::print(std::ostream &os) const
1364  {
1365  os << name << " (" << symbol << "), "
1366  << toSI << ", "
1367  << power << std::endl;
1368  }
1369 
1370 
1371 } //Antioch namespace
1372 
1373 #endif
bool is_united() const
Test if the unit is non empty.
Definition: units.h:298
void set_unit(const std::string &sym)
Units setter, sets the unit to the given symbol and name.
Definition: units.h:271
void add(Units< T > *rhs)
Alternative call to Units& operator+=(const Units &)
Definition: units.h:250
void develop_symbol(std::string &subsymbol)
Supress the parenthesises.
Definition: units.h:669
const std::string get_SI_symb() const
Corresponding SI symbol getter.
Definition: units.h:929
const std::string manipulate_symbol(std::string input, bool contract) const
Root method for contracting or harmonizing the symbol.
Definition: units.h:996
Units< T > & operator=(const Units< T > &rhs)
Assignement operator.
Definition: units.h:1262
const std::string get_symbol() const
String symbol getter.
Definition: units.h:330
Units< T > operator/(int r) const
Dividing operator by an integer, uses Units &operator/=(int)
Definition: units.h:1357
const std::string get_SI_convenient_symb() const
Corresponding SI symbol getter.
Definition: units.h:1125
int indexUnit(std::string unit) const
Scanner of knownUnits[], sends back the corresponding iUnit, -1 if not found.
Definition: units.h:840
Units< T > & operator*=(int r)
Multiplying operator by an integer.
Definition: units.h:1310
int n_dimension_of_units() const
Number of dimensions of the unit in the SI basis.
Definition: units.h:1108
Units< T > & operator/=(int r)
dividing operator by an integer
Definition: units.h:1324
void root(int r)
Alternative method to Units& operator/=(int)
Definition: units.h:266
Converter< T > raise(const Converter< T > &tbm, int power) const
Raise to an integer power a Converter object.
Definition: units.h:1230
void equalize(const Units< T > &rhs)
Alternative call to Units& operator=(const Units &)
Definition: units.h:232
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().
Definition: units.h:1252
void symbol_to_the_power(int r, const int &key)
Rewrite the symbol to put it at a given power.
Definition: units.h:1172
void set_symbol(const std::string &symb)
Symbol setter.
Definition: units.h:275
void set_SI_converter(const Converter< T > &conv)
Coefficient setter.
Definition: units.h:277
bool operator!=(const Units< T > &rhs) const
Comparison operator, not equal is not "equal".
Definition: units.h:153
void reverse_power_symbol(std::string &subsymbol)
Treat part of symbol depending on parenthesises.
Definition: units.h:1154
#define antioch_error()
Units< T > operator+(const Units< T > &rhs) const
Adding operator, uses Units &operator+=(const Units&)
Definition: units.h:1339
void add(std::string unit)
Alternative call to Units& operator+=(const Units &)
Definition: units.h:255
friend std::ostream & operator<<(std::ostream &os, const Units< T > &unit)
Formatted print.
Definition: units.h:138
const P geta() const
Multiplicative factor getter.
Definition: converter.h:61
void set_unit(const std::string &sym, std::string na)
Units setter, sets the unit to the given symbol and name.
Definition: units.h:1144
int get_integer_power(int unit, int r, const int &key)
Multiply or divide a power.
Definition: units.h:1210
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.
Definition: units.h:583
bool is_in_symb(char c) const
Small method that checks if the symbol is within a unit std::string.
Definition: units.h:1242
T get_SI_factor() const
Multiplicative coefficient getter.
Definition: units.h:334
#define antioch_unit_error(description)
bool operator==(const Units< T > &rhs) const
Comparison operator.
Units< T > & operator-=(const Units< T > &rhs)
Substracting operator.
Definition: units.h:1295
void clear()
Set all the powers to zeros.
Definition: insi.h:276
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...
Definition: units.h:774
T factor_to_some_unit(const Units< T > &target) const
Calculates the factor to any given unit.
Definition: units.h:755
void print(std::ostream &os=std::cout) const
Formatted print.
Definition: units.h:1363
void parse_prefix_unit(int &iUnit, int &iPre, const std::string &unit) const
Unit parser, parse a std::string of type Prefixes[] knownUnits[].
Definition: units.h:788
bool is_number(char c) const
Small method to check if a character is a numerical.
Definition: units.h:488
T get_SI_translator() const
Translationnal coefficient getter.
Definition: units.h:336
const Converter< T > get_SI_coef() const
Coefficient getter.
Definition: units.h:332
InSI power
An InSI for the power vector.
Definition: units.h:585
void set_power_to_SI(const InSI &mat)
Power std::vector setter.
Definition: units.h:279
const std::string add_SI(int pow, std::string SIsymb) const
Small method to add the SI symbol and power to a std::string.
Definition: units.h:977
void set_name(const std::string &na)
Name setter.
Definition: units.h:273
Seven integers to characterize the power vector.
Definition: insi.h:43
void add(const Units< T > &rhs)
Alternative call to Units& operator+=(const Units &)
Definition: units.h:248
Units< T > operator-(const Units< T > &rhs) const
Substracting operator, uses Units &operator-=(const Units&)
Definition: units.h:1345
const std::string contracted_symbol(const std::string &input="") const
Contract the symbol when possible.
Definition: units.h:387
const std::string harmonized_symbol(const std::string &input="") const
Simplify the symbol when possible.
Definition: units.h:381
bool parse_single_unit(int signe, std::string unit, bool doConv)
Calculates the corresponding coefficient and power of the given unit.
Definition: units.h:812
~Units()
Default destructor.
Definition: units.h:126
const UnitBaseConstant::SIPrefixeStore< long double > known_prefixes()
Definition: unit_defs.h:71
void clear()
Clear the unit.
Definition: units.h:390
int parse_power(std::string unit, int &nc) const
brief parser for std::string of type "some_unit power_associated".
Definition: units.h:862
bool empty() const
Check if empty (all values to zero)
Definition: insi.h:289
const InSI get_power() const
Power std::vector getter.
Definition: units.h:338
std::string symbol
Strings for the symbol.
Definition: units.h:579
const UnitBaseConstant::UnitBaseStore< long double > known_units()
Definition: unit_defs.h:65
Class to deal with the conversion between units.
Definition: converter.h:47
bool is_homogeneous(const Units< T > &rhs) const
Homogenity testing with another Units.
Definition: units.h:892
const P getb() const
Translationnal factor getter.
Definition: converter.h:64
The parameters are reduced parameters.
std::string name
Strings for the name.
Definition: units.h:581
void equalize(Units< T > *rhs)
Alternative call to Units& operator=(const Units &)
Definition: units.h:234
An advanced unit class.
Definition: units.h:111
Units< T > & operator+=(const Units< T > &rhs)
Adding operator.
Definition: units.h:1274
void substract(Units< T > *rhs)
Alternative call to Units& operator-=(const Units &)
Definition: units.h:259
Units< T > operator*(int r) const
Multiplying operator by an integer, uses Units &operator*=(int)
Definition: units.h:1351
Units()
Default constructor.
Definition: units.h:123
int get_SI_power(const std::string &SIask) const
Power of the asked SI unit.
Definition: units.h:912
const std::string get_name() const
String name getter.
Definition: units.h:328
void substract(const std::string &unit)
Alternative call to Units& operator-=(const Units &)
Definition: units.h:264
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...
Definition: units.h:623
void substract(const Units< T > &rhs)
Alternative call to Units& operator-=(const Units &)
Definition: units.h:257
T translator_to_some_unit(const std::string &target) const
Calculates the translator to any given unit, uses translator_to_some_unit(const Units&).
Definition: units.h:325
void equalize(std::string unit)
Alternative call to Units& operator=(const Units &)
Definition: units.h:246

Generated on Thu Jul 7 2016 11:09:46 for antioch-0.4.0 by  doxygen 1.8.8