thepeg is hosted by Hepforge, IPPP Durham
ThePEG  2.2.1
UnitIO.h
1 // -*- C++ -*-
2 //
3 // UnitIO.h is a part of ThePEG - Toolkit for HEP Event Generation
4 // Copyright (C) 1999-2019 Leif Lonnblad
5 //
6 // ThePEG is licenced under version 3 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 namespace ThePEG {
21 
35 template <typename T, typename UT>
36 struct OUnit {
37 
40  OUnit(const T & t, const UT & u): theX(t), theUnit(u) {}
41 
43  OUnit(const OUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
44 
46  const T & theX;
47 
49  const UT & theUnit;
50 };
51 
63 template <typename T, typename UT>
64 struct IUnit {
65 
68  IUnit(T & t, const UT & u): theX(t), theUnit(u) {}
69 
71  IUnit(const IUnit<T,UT> & iu): theX(iu.theX), theUnit(iu.theUnit) {}
72 
74  T & theX;
75 
77  const UT & theUnit;
78 
79 };
80 
83 template <typename T, typename UT>
84 inline OUnit<T,UT> ounit(const T & t, const UT & ut) {
85  return OUnit<T,UT>(t, ut);
86 }
87 
90 template <typename T, typename UT>
91 inline IUnit<T,UT> iunit(T & t, const UT & ut) {
92  return IUnit<T,UT>(t, ut);
93 }
94 
97 template <typename OStream, typename T, typename UT>
98 void ounitstream(OStream & os, const T & t, UT & u) {
99  os << t/u;
100 }
101 
104 template <typename IStream, typename T, typename UT>
105 void iunitstream(IStream & is, T & t, UT & u) {
106  double d;
107  is >> d;
108  t = d*u;;
109 }
110 
113 template <typename IStream, typename T, typename UT>
114 void iunitstream(IStream & is, std::complex<T> & t, UT & u) {
115  std::complex<double> d;
116  is >> d;
117  t = d*u;;
118 }
119 
121 template <typename OStream, typename T, typename UT>
122 OStream & operator<<(OStream & os, const OUnit<T,UT> & u) {
123  ounitstream(os, u.theX, u.theUnit);
124  return os;
125 }
126 
128 template <typename IStream, typename T, typename UT>
129 IStream & operator>>(IStream & is, const IUnit<T,UT> & u) {
130  iunitstream(is, u.theX, u.theUnit);
131  return is;
132 }
133 
145 template <typename T, typename UT>
146 struct OUnitErr {
147 
150  OUnitErr(const T & t, const T & dt, const UT & u): x(t/u), dx(dt/u) {}
151 
153  double x;
154 
156  double dx;
157 
158 };
159 
161 template <typename T, typename UT>
162 inline OUnitErr<T,UT> ouniterr(const T & t, const T & dt, const UT & ut) {
163  return OUnitErr<T,UT>(t, dt, ut);
164 }
165 
167 inline OUnitErr<double,double> ouniterr(double t, double dt) {
168  return OUnitErr<double,double>(t, dt, 1.0);
169 }
170 
172 template <typename OStream, typename T, typename UT>
173 OStream & operator<<(OStream & os, const OUnitErr<T,UT> & u) {
174  if ( ! isfinite(u.x) ) return os << u.x;
175  if ( ! isfinite(u.dx) ) {
176  ostringstream out;
177  out << u.x << '(' << u.dx << ')';
178  return os << out.str();
179  }
180  double dx = min(u.dx, abs(u.x));
181  if ( dx <= 0.0 ) return os << u.x;
182  double x = abs(u.x);
183  ostringstream osse;
184  osse << std::scientific << setprecision(0) << dx;
185  string sse = osse.str();
186  string::size_type ee = sse.find('e');
187  long m = static_cast<long>(round(abs(x)/std::pow(10.0,std::atoi(sse.substr(ee + 1).c_str()))));
188  int powx = m <= 0? os.precision(): int(log10(double(m)));
189  if ( m <= 0 || powx > os.precision() ) sse[0]='0';
190  ostringstream oss;
191  oss << std::scientific << setprecision(powx) << x;
192  string ss = oss.str();
193  string::size_type e = ss.find('e');
194  ostringstream out;
195  int pp = std::atoi(ss.substr(e + 1).c_str());
196  if ( pp%3 == 0 )
197  out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
198  else if ( (pp - 1)%3 == 0 ) {
199  ostringstream oss;
200  oss << std::scientific << setprecision(powx) << x/10.0;
201  string ss = oss.str();
202  string::size_type e = ss.find('e');
203  if ( powx == 0 )
204  out << ss.substr(0, e) << "0(" << sse[0] << "0)" << ss.substr(e);
205  else if ( powx == 1 )
206  out << ss.substr(0, ss.find('.'))
207  << ss.substr(ss.find('.') + 1, e - ss.find('.') - 1)
208  << "(" << sse[0] << ")" << ss.substr(e);
209  else {
210  swap(ss[ss.find('.')], ss[ss.find('.') + 1]);
211  out << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
212  }
213  }
214  else {
215  ostringstream oss;
216  oss << std::scientific << setprecision(powx) << x*10.0;
217  string ss = oss.str();
218  string::size_type e = ss.find('e');
219  if ( powx == 0 )
220  out << "0." << ss.substr(0, e) << "(" << sse[0] << ")" << ss.substr(e);
221  else {
222  swap(ss[ss.find('.')], ss[ss.find('.') - 1]);
223  out << ss.substr(0, ss.find('.')) << "0" << ss.substr(ss.find('.'), e)
224  << "(" << sse[0] << ")" << ss.substr(e);
225  }
226  }
227  string res = out.str();
228  if ( u.x < 0.0 )
229  res = "-" + res;
230  return os << res;
231 }
232 
238 template <typename T, typename UT>
239 struct IUnitErr {
240 
243  IUnitErr(T & t, T & dt, const UT & u): x(t), dx(dt), ut(u) {}
244 
246  T & x;
247 
249  T & dx;
250 
252  UT ut;
253 
254 };
255 
257 template <typename T, typename UT>
258 inline IUnitErr<T,UT> iuniterr(T & t, T & dt, const UT & ut) {
259  return IUnitErr<T,UT>(t, dt, ut);
260 }
261 
263 inline IUnitErr<double,double> iuniterr(double & t, double & dt) {
264  return IUnitErr<double,double>(t, dt, 1.0);
265 }
266 
268 template <typename IStream, typename T, typename UT>
269 IStream & operator>>(IStream & is, const IUnitErr<T,UT> & u) {
270  string s;
271  double x = 0.0;
272  double dx = 0.0;
273  double ex = 1.0;
274  is >> s;
275  string::size_type open = s.find('(');
276  string::size_type close = s.find(')');
277  string se = "0";
278  string sp = "1";
279  double pe = 1.0;
280  if ( open != string::npos && close != string::npos ) {
281  se = s.substr(open + 1);
282  sp += s.substr(close + 1);
283  string::size_type dot = s.find('.');
284  if ( dot != string::npos && dot < open ) pe = std::pow(10.0, 1.0 - (open - dot));
285  }
286 
287  istringstream(s) >> x;
288  istringstream(se) >> dx;
289  istringstream(sp) >> ex;
290 
291  u.x = x*ex*u.ut;
292  u.dx = dx*ex*pe*u.ut;
293 
294  return is;
295 }
296 
297 }
298 
299 #endif /* ThePEG_UnitIO_H */
IUnit(const IUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:71
OUnitErr< T, UT > ouniterr(const T &t, const T &dt, const UT &ut)
Helper function creating a OUnitErr object.
Definition: UnitIO.h:162
OUnitErr is used to write out unitful numbers with an error estimate on a standard ostream...
Definition: UnitIO.h:146
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:156
OUnit(const OUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:43
double x
The number to be written.
Definition: UnitIO.h:153
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:36
const T & theX
Reference to the object to be written.
Definition: UnitIO.h:46
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:40
IUnitErr(T &t, T &dt, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:243
The IUnit class is used to facilitate input of unitful numbers from and to a persistent stream...
Definition: UnitIO.h:64
IUnit(T &t, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:68
UT ut
The unit assumed when reading the object.
Definition: UnitIO.h:252
T & dx
The estimated error of the number to be read.
Definition: UnitIO.h:249
const UT & theUnit
The unit assumed when writing the object.
Definition: UnitIO.h:49
const UT & theUnit
The unit assumed when reading the object.
Definition: UnitIO.h:77
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:84
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:150
The IUnitErr class is used to facilitate input of unitful numbers with error estimates written out us...
Definition: UnitIO.h:239
IUnitErr< T, UT > iuniterr(T &t, T &dt, const UT &ut)
Helper function creating a IUnitErr object.
Definition: UnitIO.h:258
T & theX
Reference to the object to be read.
Definition: UnitIO.h:74
T & x
Reference to the object to be read.
Definition: UnitIO.h:246
IUnit< T, UT > iunit(T &t, const UT &ut)
Helper function creating a IUnit object given an object and a unit.
Definition: UnitIO.h:91