ThePEG  1.8.0
UnitIO.h
1 // -*- C++ -*-
2 //
3 // UnitIO.h is a part of ThePEG - Toolkit for HEP Event Generation
4 // Copyright (C) 1999-2011 Leif Lonnblad
5 //
6 // ThePEG is licenced under version 2 of the GPL, see COPYING for details.
7 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
8 //
9 #ifndef ThePEG_UnitIO_H
10 #define ThePEG_UnitIO_H
11 // This is the declaration of the IUnit and OUnit classes and
12 // associated templated functions.
13 
14 #include <complex>
15 #include <iomanip>
16 #include <sstream>
17 #include <cstdlib>
18 #include <cmath>
19 
20 // Workarounds for OS X
21 #if defined __APPLE__ && defined __MACH__
22 extern "C" int isnan(double) throw();
23 extern "C" int isinf(double) throw();
24 #endif
25 
26 namespace ThePEG {
27 
41 template <typename T, typename UT>
42 struct OUnit {
43 
46  OUnit(const T & t, const UT & u): theX(t), theUnit(u) {}
47 
49  OUnit(const OUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
50 
52  const T & theX;
53 
55  const UT & theUnit;
56 };
57 
69 template <typename T, typename UT>
70 struct IUnit {
71 
74  IUnit(T & t, const UT & u): theX(t), theUnit(u) {}
75 
77  IUnit(const IUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
78 
80  T & theX;
81 
83  const UT & theUnit;
84 
85 };
86 
89 template <typename T, typename UT>
90 inline OUnit<T,UT> ounit(const T & t, const UT & ut) {
91  return OUnit<T,UT>(t, ut);
92 }
93 
96 template <typename T, typename UT>
97 inline IUnit<T,UT> iunit(T & t, const UT & ut) {
98  return IUnit<T,UT>(t, ut);
99 }
100 
103 template <typename OStream, typename T, typename UT>
104 void ounitstream(OStream & os, const T & t, UT & u) {
105  os << t/u;
106 }
107 
110 template <typename IStream, typename T, typename UT>
111 void iunitstream(IStream & is, T & t, UT & u) {
112  double d;
113  is >> d;
114  t = d*u;;
115 }
116 
119 template <typename IStream, typename T, typename UT>
120 void iunitstream(IStream & is, std::complex<T> & t, UT & u) {
121  std::complex<double> d;
122  is >> d;
123  t = d*u;;
124 }
125 
127 template <typename OStream, typename T, typename UT>
128 OStream & operator<<(OStream & os, const OUnit<T,UT> & u) {
129  ounitstream(os, u.theX, u.theUnit);
130  return os;
131 }
132 
134 template <typename IStream, typename T, typename UT>
135 IStream & operator>>(IStream & is, const IUnit<T,UT> & u) {
136  iunitstream(is, u.theX, u.theUnit);
137  return is;
138 }
139 
151 template <typename T, typename UT>
152 struct OUnitErr {
153 
156  OUnitErr(const T & t, const T & dt, const UT & u): x(t/u), dx(dt/u) {}
157 
159  double x;
160 
162  double dx;
163 
164 };
165 
167 template <typename T, typename UT>
168 inline OUnitErr<T,UT> ouniterr(const T & t, const T & dt, const UT & ut) {
169  return OUnitErr<T,UT>(t, dt, ut);
170 }
171 
173 inline OUnitErr<double,double> ouniterr(double t, double dt) {
174  return OUnitErr<double,double>(t, dt, 1.0);
175 }
176 
178 template <typename OStream, typename T, typename UT>
179 OStream & operator<<(OStream & os, const OUnitErr<T,UT> & u) {
180  if ( isnan(u.x) || isinf(u.x) ) return os << u.x;
181  if ( isnan(u.dx) || isinf(u.dx) ) return os << u.x << '(' << u.dx << ')';
182  double dx = min(u.dx, abs(u.x));
183  if ( dx <= 0.0 ) return os << u.x;
184  ostringstream osse;
185  osse << std::scientific << setprecision(0) << dx;
186  string sse = osse.str();
187  string::size_type ee = sse.find('e');
188  long m = static_cast<long>(round(abs(u.x)/std::pow(10.0,std::atoi(sse.substr(ee + 1).c_str()))));
189  int powx = m <= 0? os.precision(): int(log10(double(m)));
190  if ( m <= 0 || powx > os.precision() ) sse[0]='0';
191  ostringstream oss;
192  oss << std::scientific << setprecision(powx) << u.x;
193  string ss = oss.str();
194  string::size_type e = ss.find('e');
195  ostringstream out;
196  int pp = std::atoi(ss.substr(e + 1).c_str());
197  if ( pp%3 == 0 )
198  out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
199  else if ( (pp - 1)%3 == 0 ) {
200  ostringstream oss;
201  oss << std::scientific << setprecision(powx) << u.x/10.0;
202  string ss = oss.str();
203  string::size_type e = ss.find('e');
204  if ( powx == 0 )
205  out << ss.substr(0, e) << "0(" << sse[0] << "0)" << ss.substr(e);
206  else if ( powx == 1 )
207  out << ss.substr(0, ss.find('.'))
208  << ss.substr(ss.find('.') + 1, e - ss.find('.') - 1)
209  << "(" << sse[0] << ")" << ss.substr(e);
210  else {
211  swap(ss[ss.find('.')], ss[ss.find('.') + 1]);
212  out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
213  }
214  }
215  else {
216  ostringstream oss;
217  oss << std::scientific << setprecision(powx) << u.x*10.0;
218  string ss = oss.str();
219  string::size_type e = ss.find('e');
220  if ( powx == 0 )
221  out << "0." << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
222  else {
223  swap(ss[ss.find('.')], ss[ss.find('.') - 1]);
224  out << ss.substr(0, ss.find('.')) << "0" << ss.substr(ss.find('.'), e)
225  << "(" << sse[0] << ")" << ss.substr(e);
226  }
227  }
228  return os << out.str();
229 }
230 
236 template <typename T, typename UT>
237 struct IUnitErr {
238 
241  IUnitErr(T & t, T & dt, const UT & u): x(t), dx(dt), ut(u) {}
242 
244  T & x;
245 
247  T & dx;
248 
250  UT ut;
251 
252 };
253 
255 template <typename T, typename UT>
256 inline IUnitErr<T,UT> iuniterr(T & t, T & dt, const UT & ut) {
257  return IUnitErr<T,UT>(t, dt, ut);
258 }
259 
261 inline IUnitErr<double,double> iuniterr(double & t, double & dt) {
262  return IUnitErr<double,double>(t, dt, 1.0);
263 }
264 
266 template <typename IStream, typename T, typename UT>
267 IStream & operator>>(IStream & is, const IUnitErr<T,UT> & u) {
268  string s;
269  double x = 0.0;
270  double dx = 0.0;
271  double ex = 1.0;
272  is >> s;
273  string::size_type open = s.find('(');
274  string::size_type close = s.find(')');
275  string se = "0";
276  string sp = "1";
277  double pe = 1.0;
278  if ( open != string::npos && close != string::npos ) {
279  se = s.substr(open + 1);
280  sp += s.substr(close + 1);
281  string::size_type dot = s.find('.');
282  if ( dot != string::npos && dot < open ) pe = std::pow(10.0, 1.0 - (open - dot));
283  }
284 
285  istringstream(s) >> x;
286  istringstream(se) >> dx;
287  istringstream(sp) >> ex;
288 
289  u.x = x*ex*u.ut;
290  u.dx = dx*ex*pe*u.ut;
291 
292  return is;
293 }
294 
295 }
296 
297 #endif /* ThePEG_UnitIO_H */
IUnit(const IUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:77
OUnitErr< T, UT > ouniterr(const T &t, const T &dt, const UT &ut)
Helper function creating a OUnitErr object.
Definition: UnitIO.h:168
OUnitErr is used to write out unitful numbers with an error estimate on a standard ostream...
Definition: UnitIO.h:152
void ounitstream(OStream &os, const vector< T, Alloc > &v, UT &u)
Ouput a vector of objects with the specified unit.
Definition: Containers.h:275
double dx
The estimated error of the number to be written.
Definition: UnitIO.h:162
OUnit(const OUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:49
double x
The number to be written.
Definition: UnitIO.h:159
This is the main namespace within which all identifiers in ThePEG are declared.
Definition: FactoryBase.h:28
The OUnit< class is used to facilitate output of unitful numbers to a persistent stream.
Definition: UnitIO.h:42
const T & theX
Reference to the object to be written.
Definition: UnitIO.h:52
void iunitstream(IStream &is, vector< T, Alloc > &v, UT &u)
Input a vector of objects with the specified unit.
Definition: Containers.h:289
OUnit(const T &t, const UT &u)
Constructor given an object to be written assuming the given unit.
Definition: UnitIO.h:46
IUnitErr(T &t, T &dt, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:241
The IUnit class is used to facilitate input of unitful numbers from and to a persistent stream...
Definition: UnitIO.h:70
IUnit(T &t, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:74
UT ut
The unit assumed when reading the object.
Definition: UnitIO.h:250
T & dx
The estimated error of the number to be read.
Definition: UnitIO.h:247
const UT & theUnit
The unit assumed when writing the object.
Definition: UnitIO.h:55
const UT & theUnit
The unit assumed when reading the object.
Definition: UnitIO.h:83
OUnit< T, UT > ounit(const T &t, const UT &ut)
Helper function creating a OUnit object given an object and a unit.
Definition: UnitIO.h:90
vector< T > & operator>>(vector< T > &tv, U &u)
Overload the right shift operator for vector to pop objects from a vector.
Definition: Containers.h:192
OUnitErr(const T &t, const T &dt, const UT &u)
Constructor given an object to be written assuming the given unit.
Definition: UnitIO.h:156
The IUnitErr class is used to facilitate input of unitful numbers with error estimates written out us...
Definition: UnitIO.h:237
IUnitErr< T, UT > iuniterr(T &t, T &dt, const UT &ut)
Helper function creating a IUnitErr object.
Definition: UnitIO.h:256
T & theX
Reference to the object to be read.
Definition: UnitIO.h:80
T & x
Reference to the object to be read.
Definition: UnitIO.h:244
IUnit< T, UT > iunit(T &t, const UT &ut)
Helper function creating a IUnit object given an object and a unit.
Definition: UnitIO.h:97