00001
00002
00003
00004
00005
00006
00007
00008
00009 #ifndef ThePEG_UnitIO_H
00010 #define ThePEG_UnitIO_H
00011
00012
00013
00014 #include <complex>
00015 #include <iomanip>
00016 #include <sstream>
00017 #include <cstdlib>
00018 #include <cmath>
00019
00020
00021 extern "C" int isnan(double) throw();
00022 extern "C" int isinf(double) throw();
00023
00024 namespace ThePEG {
00025
00026 using namespace std;
00027
00041 template <typename T, typename UT>
00042 struct OUnit {
00043
00046 OUnit(const T & t, const UT & u): theX(t), theUnit(u) {}
00047
00049 OUnit(const OUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
00050
00052 const T & theX;
00053
00055 const UT & theUnit;
00056 };
00057
00069 template <typename T, typename UT>
00070 struct IUnit {
00071
00074 IUnit(T & t, const UT & u): theX(t), theUnit(u) {}
00075
00077 IUnit(const IUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
00078
00080 T & theX;
00081
00083 const UT & theUnit;
00084
00085 };
00086
00089 template <typename T, typename UT>
00090 inline OUnit<T,UT> ounit(const T & t, const UT & ut) {
00091 return OUnit<T,UT>(t, ut);
00092 }
00093
00096 template <typename T, typename UT>
00097 inline IUnit<T,UT> iunit(T & t, const UT & ut) {
00098 return IUnit<T,UT>(t, ut);
00099 }
00100
00103 template <typename OStream, typename T, typename UT>
00104 void ounitstream(OStream & os, const T & t, UT & u) {
00105 os << t/u;
00106 }
00107
00110 template <typename IStream, typename T, typename UT>
00111 void iunitstream(IStream & is, T & t, UT & u) {
00112 double d;
00113 is >> d;
00114 t = d*u;;
00115 }
00116
00119 template <typename IStream, typename T, typename UT>
00120 void iunitstream(IStream & is, std::complex<T> & t, UT & u) {
00121 std::complex<double> d;
00122 is >> d;
00123 t = d*u;;
00124 }
00125
00127 template <typename OStream, typename T, typename UT>
00128 OStream & operator<<(OStream & os, const OUnit<T,UT> & u) {
00129 ounitstream(os, u.theX, u.theUnit);
00130 return os;
00131 }
00132
00134 template <typename IStream, typename T, typename UT>
00135 IStream & operator>>(IStream & is, const IUnit<T,UT> & u) {
00136 iunitstream(is, u.theX, u.theUnit);
00137 return is;
00138 }
00139
00151 template <typename T, typename UT>
00152 struct OUnitErr {
00153
00156 OUnitErr(const T & t, const T & dt, const UT & u): x(t/u), dx(dt/u) {}
00157
00159 double x;
00160
00162 double dx;
00163
00164 };
00165
00167 template <typename T, typename UT>
00168 inline OUnitErr<T,UT> ouniterr(const T & t, const T & dt, const UT & ut) {
00169 return OUnitErr<T,UT>(t, dt, ut);
00170 }
00171
00173 inline OUnitErr<double,double> ouniterr(double t, double dt) {
00174 return OUnitErr<double,double>(t, dt, 1.0);
00175 }
00176
00178 template <typename OStream, typename T, typename UT>
00179 OStream & operator<<(OStream & os, const OUnitErr<T,UT> & u) {
00180 if ( isnan(u.x) || isinf(u.x) ) return os << u.x;
00181 if ( isnan(u.dx) || isinf(u.dx) ) return os << u.x << '(' << u.dx << ')';
00182 double dx = min(u.dx, abs(u.x));
00183 if ( dx <= 0.0 ) return os << u.x;
00184 ostringstream osse;
00185 osse << std::scientific << setprecision(0) << dx;
00186 string sse = osse.str();
00187 string::size_type ee = sse.find('e');
00188 long m = static_cast<long>(round(abs(u.x)/std::pow(10.0,std::atoi(sse.substr(ee + 1).c_str()))));
00189 int powx = m <= 0? os.precision(): int(log10(double(m)));
00190 if ( m <= 0 || powx > os.precision() ) sse[0]='0';
00191 ostringstream oss;
00192 oss << std::scientific << setprecision(powx) << u.x;
00193 string ss = oss.str();
00194 string::size_type e = ss.find('e');
00195 ostringstream out;
00196 int pp = std::atoi(ss.substr(e + 1).c_str());
00197 if ( pp%3 == 0 )
00198 out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
00199 else if ( (pp - 1)%3 == 0 ) {
00200 ostringstream oss;
00201 oss << std::scientific << setprecision(powx) << u.x/10.0;
00202 string ss = oss.str();
00203 string::size_type e = ss.find('e');
00204 if ( powx == 0 )
00205 out << ss.substr(0, e) << "0(" << sse[0] << "0)" << ss.substr(e);
00206 else if ( powx == 1 )
00207 out << ss.substr(0, ss.find('.'))
00208 << ss.substr(ss.find('.') + 1, e - ss.find('.') - 1)
00209 << "(" << sse[0] << ")" << ss.substr(e);
00210 else {
00211 swap(ss[ss.find('.')], ss[ss.find('.') + 1]);
00212 out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
00213 }
00214 }
00215 else {
00216 ostringstream oss;
00217 oss << std::scientific << setprecision(powx) << u.x*10.0;
00218 string ss = oss.str();
00219 string::size_type e = ss.find('e');
00220 if ( powx == 0 )
00221 out << "0." << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
00222 else {
00223 swap(ss[ss.find('.')], ss[ss.find('.') - 1]);
00224 out << ss.substr(0, ss.find('.')) << "0" << ss.substr(ss.find('.'), e)
00225 << "(" << sse[0] << ")" << ss.substr(e);
00226 }
00227 }
00228 return os << out.str();
00229 }
00230
00236 template <typename T, typename UT>
00237 struct IUnitErr {
00238
00241 IUnitErr(T & t, T & dt, const UT & u): x(t), dx(dt), ut(u) {}
00242
00244 T & x;
00245
00247 T & dx;
00248
00250 UT ut;
00251
00252 };
00253
00255 template <typename T, typename UT>
00256 inline IUnitErr<T,UT> iuniterr(T & t, T & dt, const UT & ut) {
00257 return IUnitErr<T,UT>(t, dt, ut);
00258 }
00259
00261 inline IUnitErr<double,double> iuniterr(double & t, double & dt) {
00262 return IUnitErr<double,double>(t, dt, 1.0);
00263 }
00264
00266 template <typename IStream, typename T, typename UT>
00267 IStream & operator>>(IStream & is, const IUnitErr<T,UT> & u) {
00268 string s;
00269 double x = 0.0;
00270 double dx = 0.0;
00271 double ex = 1.0;
00272 is >> s;
00273 string::size_type open = s.find('(');
00274 string::size_type close = s.find(')');
00275 string se = "0";
00276 string sp = "1";
00277 double pe = 1.0;
00278 if ( open != string::npos && close != string::npos ) {
00279 se = s.substr(open + 1);
00280 sp += s.substr(close + 1);
00281 string::size_type dot = s.find('.');
00282 if ( dot != string::npos && dot < open ) pe = std::pow(10.0, 1.0 - (open - dot));
00283 }
00284
00285 istringstream(s) >> x;
00286 istringstream(se) >> dx;
00287 istringstream(sp) >> ex;
00288
00289 u.x = x*ex*u.ut;
00290 u.dx = dx*ex*pe*u.ut;
00291
00292 return is;
00293 }
00294
00295 }
00296
00297 #endif