File indexing completed on 2026-08-06 09:38:32
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef ThePEG_UnitIO_H
0010 #define ThePEG_UnitIO_H
0011
0012
0013
0014 #include <complex>
0015 #include <iomanip>
0016 #include <sstream>
0017 #include <cstdlib>
0018 #include <cmath>
0019
0020 namespace ThePEG {
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 template <typename T, typename UT>
0036 struct OUnit {
0037
0038
0039
0040 OUnit(const T & t, const UT & u): theX(t), theUnit(u) {}
0041
0042
0043 OUnit(const OUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
0044
0045
0046 const T & theX;
0047
0048
0049 const UT & theUnit;
0050 };
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 template <typename T, typename UT>
0064 struct IUnit {
0065
0066
0067
0068 IUnit(T & t, const UT & u): theX(t), theUnit(u) {}
0069
0070
0071 IUnit(const IUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
0072
0073
0074 T & theX;
0075
0076
0077 const UT & theUnit;
0078
0079 };
0080
0081
0082
0083 template <typename T, typename UT>
0084 inline OUnit<T,UT> ounit(const T & t, const UT & ut) {
0085 return OUnit<T,UT>(t, ut);
0086 }
0087
0088
0089
0090 template <typename T, typename UT>
0091 inline IUnit<T,UT> iunit(T & t, const UT & ut) {
0092 return IUnit<T,UT>(t, ut);
0093 }
0094
0095
0096
0097 template <typename OStream, typename T, typename UT>
0098 void ounitstream(OStream & os, const T & t, UT & u) {
0099 os << t/u;
0100 }
0101
0102
0103
0104 template <typename IStream, typename T, typename UT>
0105 void iunitstream(IStream & is, T & t, UT & u) {
0106 double d;
0107 is >> d;
0108 t = d*u;;
0109 }
0110
0111
0112
0113 template <typename IStream, typename T, typename UT>
0114 void iunitstream(IStream & is, std::complex<T> & t, UT & u) {
0115 std::complex<double> d;
0116 is >> d;
0117 t = d*u;;
0118 }
0119
0120
0121 template <typename OStream, typename T, typename UT>
0122 OStream & operator<<(OStream & os, const OUnit<T,UT> & u) {
0123 ounitstream(os, u.theX, u.theUnit);
0124 return os;
0125 }
0126
0127
0128 template <typename IStream, typename T, typename UT>
0129 IStream & operator>>(IStream & is, const IUnit<T,UT> & u) {
0130 iunitstream(is, u.theX, u.theUnit);
0131 return is;
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143
0144
0145 template <typename T, typename UT>
0146 struct OUnitErr {
0147
0148
0149
0150 OUnitErr(const T & t, const T & dt, const UT & u): x(t/u), dx(dt/u) {}
0151
0152
0153 double x;
0154
0155
0156 double dx;
0157
0158 };
0159
0160
0161 template <typename T, typename UT>
0162 inline OUnitErr<T,UT> ouniterr(const T & t, const T & dt, const UT & ut) {
0163 return OUnitErr<T,UT>(t, dt, ut);
0164 }
0165
0166
0167 inline OUnitErr<double,double> ouniterr(double t, double dt) {
0168 return OUnitErr<double,double>(t, dt, 1.0);
0169 }
0170
0171
0172 template <typename OStream, typename T, typename UT>
0173 OStream & operator<<(OStream & os, const OUnitErr<T,UT> & u) {
0174 if ( ! isfinite(u.x) ) return os << u.x;
0175 if ( ! isfinite(u.dx) ) {
0176 ostringstream out;
0177 out << u.x << '(' << u.dx << ')';
0178 return os << out.str();
0179 }
0180 double dx = min(u.dx, abs(u.x));
0181 if ( dx <= 0.0 ) return os << u.x;
0182 double x = abs(u.x);
0183 ostringstream osse;
0184 osse << std::scientific << setprecision(0) << dx;
0185 string sse = osse.str();
0186 string::size_type ee = sse.find('e');
0187 long m = static_cast<long>(round(abs(x)/std::pow(10.0,std::atoi(sse.substr(ee + 1).c_str()))));
0188 int powx = m <= 0? os.precision(): int(log10(double(m)));
0189 if ( m <= 0 || powx > os.precision() ) sse[0]='0';
0190 ostringstream oss;
0191 oss << std::scientific << setprecision(powx) << x;
0192 string ss = oss.str();
0193 string::size_type e = ss.find('e');
0194 ostringstream out;
0195 int pp = std::atoi(ss.substr(e + 1).c_str());
0196 if ( pp%3 == 0 )
0197 out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
0198 else if ( (pp - 1)%3 == 0 ) {
0199 ostringstream oss;
0200 oss << std::scientific << setprecision(powx) << x/10.0;
0201 string ss = oss.str();
0202 string::size_type e = ss.find('e');
0203 if ( powx == 0 )
0204 out << ss.substr(0, e) << "0(" << sse[0] << "0)" << ss.substr(e);
0205 else if ( powx == 1 )
0206 out << ss.substr(0, ss.find('.'))
0207 << ss.substr(ss.find('.') + 1, e - ss.find('.') - 1)
0208 << "(" << sse[0] << ")" << ss.substr(e);
0209 else {
0210 swap(ss[ss.find('.')], ss[ss.find('.') + 1]);
0211 out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
0212 }
0213 }
0214 else {
0215 ostringstream oss;
0216 oss << std::scientific << setprecision(powx) << x*10.0;
0217 string ss = oss.str();
0218 string::size_type e = ss.find('e');
0219 if ( powx == 0 )
0220 out << "0." << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
0221 else {
0222 swap(ss[ss.find('.')], ss[ss.find('.') - 1]);
0223 out << ss.substr(0, ss.find('.')) << "0" << ss.substr(ss.find('.'), e)
0224 << "(" << sse[0] << ")" << ss.substr(e);
0225 }
0226 }
0227 string res = out.str();
0228 if ( u.x < 0.0 )
0229 res = "-" + res;
0230 return os << res;
0231 }
0232
0233
0234
0235
0236
0237
0238 template <typename T, typename UT>
0239 struct IUnitErr {
0240
0241
0242
0243 IUnitErr(T & t, T & dt, const UT & u): x(t), dx(dt), ut(u) {}
0244
0245
0246 T & x;
0247
0248
0249 T & dx;
0250
0251
0252 UT ut;
0253
0254 };
0255
0256
0257 template <typename T, typename UT>
0258 inline IUnitErr<T,UT> iuniterr(T & t, T & dt, const UT & ut) {
0259 return IUnitErr<T,UT>(t, dt, ut);
0260 }
0261
0262
0263 inline IUnitErr<double,double> iuniterr(double & t, double & dt) {
0264 return IUnitErr<double,double>(t, dt, 1.0);
0265 }
0266
0267
0268 template <typename IStream, typename T, typename UT>
0269 IStream & operator>>(IStream & is, const IUnitErr<T,UT> & u) {
0270 string s;
0271 double x = 0.0;
0272 double dx = 0.0;
0273 double ex = 1.0;
0274 is >> s;
0275 string::size_type open = s.find('(');
0276 string::size_type close = s.find(')');
0277 string se = "0";
0278 string sp = "1";
0279 double pe = 1.0;
0280 if ( open != string::npos && close != string::npos ) {
0281 se = s.substr(open + 1);
0282 sp += s.substr(close + 1);
0283 string::size_type dot = s.find('.');
0284 if ( dot != string::npos && dot < open ) pe = std::pow(10.0, 1.0 - (open - dot));
0285 }
0286
0287 istringstream(s) >> x;
0288 istringstream(se) >> dx;
0289 istringstream(sp) >> ex;
0290
0291 u.x = x*ex*u.ut;
0292 u.dx = dx*ex*pe*u.ut;
0293
0294 return is;
0295 }
0296
0297 }
0298
0299 #endif