thepeg is hosted by Hepforge, IPPP Durham
ThePEG 2.3.0
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
20namespace ThePEG {
21
35template <typename T, typename UT>
36struct 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
63template <typename T, typename UT>
64struct 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
83template <typename T, typename UT>
84inline OUnit<T,UT> ounit(const T & t, const UT & ut) {
85 return OUnit<T,UT>(t, ut);
86}
87
90template <typename T, typename UT>
91inline IUnit<T,UT> iunit(T & t, const UT & ut) {
92 return IUnit<T,UT>(t, ut);
93}
94
97template <typename OStream, typename T, typename UT>
98void ounitstream(OStream & os, const T & t, UT & u) {
99 os << t/u;
100}
101
104template <typename IStream, typename T, typename UT>
105void iunitstream(IStream & is, T & t, UT & u) {
106 double d;
107 is >> d;
108 t = d*u;;
109}
110
113template <typename IStream, typename T, typename UT>
114void iunitstream(IStream & is, std::complex<T> & t, UT & u) {
115 std::complex<double> d;
116 is >> d;
117 t = d*u;;
118}
119
121template <typename OStream, typename T, typename UT>
122OStream & operator<<(OStream & os, const OUnit<T,UT> & u) {
123 ounitstream(os, u.theX, u.theUnit);
124 return os;
125}
126
128template <typename IStream, typename T, typename UT>
129IStream & operator>>(IStream & is, const IUnit<T,UT> & u) {
130 iunitstream(is, u.theX, u.theUnit);
131 return is;
132}
133
145template <typename T, typename UT>
146struct 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
161template <typename T, typename UT>
162inline OUnitErr<T,UT> ouniterr(const T & t, const T & dt, const UT & ut) {
163 return OUnitErr<T,UT>(t, dt, ut);
164}
165
167inline OUnitErr<double,double> ouniterr(double t, double dt) {
168 return OUnitErr<double,double>(t, dt, 1.0);
169}
170
172template <typename OStream, typename T, typename UT>
173OStream & 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
238template <typename T, typename UT>
239struct 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
257template <typename T, typename UT>
258inline IUnitErr<T,UT> iuniterr(T & t, T & dt, const UT & ut) {
259 return IUnitErr<T,UT>(t, dt, ut);
260}
261
263inline IUnitErr<double,double> iuniterr(double & t, double & dt) {
264 return IUnitErr<double,double>(t, dt, 1.0);
265}
266
268template <typename IStream, typename T, typename UT>
269IStream & 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 */
This is the main namespace within which all identifiers in ThePEG are declared.
Definition: FactoryBase.h:28
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
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
void iunitstream(IStream &is, vector< T, Alloc > &v, UT &u)
Input a vector of objects with the specified unit.
Definition: Containers.h:289
vector< T > & operator<<(vector< T > &tv, const U &u)
Overload the left shift operator for vector to push_back objects to a vector.
Definition: Containers.h:179
IUnitErr< T, UT > iuniterr(T &t, T &dt, const UT &ut)
Helper function creating a IUnitErr object.
Definition: UnitIO.h:258
void ounitstream(OStream &os, const vector< T, Alloc > &v, UT &u)
Ouput a vector of objects with the specified unit.
Definition: Containers.h:275
OUnitErr< T, UT > ouniterr(const T &t, const T &dt, const UT &ut)
Helper function creating a OUnitErr object.
Definition: UnitIO.h:162
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
The IUnitErr class is used to facilitate input of unitful numbers with error estimates written out us...
Definition: UnitIO.h:239
IUnitErr(T &t, T &dt, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:243
UT ut
The unit assumed when reading the object.
Definition: UnitIO.h:252
T & x
Reference to the object to be read.
Definition: UnitIO.h:246
T & dx
The estimated error of the number to be read.
Definition: UnitIO.h:249
The IUnit class is used to facilitate input of unitful numbers from and to a persistent stream.
Definition: UnitIO.h:64
const UT & theUnit
The unit assumed when reading the object.
Definition: UnitIO.h:77
IUnit(T &t, const UT &u)
Constructor given an object to be read assuming the given unit.
Definition: UnitIO.h:68
T & theX
Reference to the object to be read.
Definition: UnitIO.h:74
IUnit(const IUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:71
OUnitErr is used to write out unitful numbers with an error estimate on a standard ostream.
Definition: UnitIO.h:146
double x
The number to be written.
Definition: UnitIO.h:153
double dx
The estimated error of the number to be written.
Definition: UnitIO.h:156
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 OUnit< class is used to facilitate output of unitful numbers to a persistent stream.
Definition: UnitIO.h:36
const UT & theUnit
The unit assumed when writing the object.
Definition: UnitIO.h:49
OUnit(const T &t, const UT &u)
Constructor given an object to be written assuming the given unit.
Definition: UnitIO.h:40
OUnit(const OUnit< T, UT > &iu)
Copy constructor.
Definition: UnitIO.h:43
const T & theX
Reference to the object to be written.
Definition: UnitIO.h:46