CORSIKA  @c8_version@
The framework to simulate particle cascades for astroparticle physics
quantity_io.hpp
Go to the documentation of this file.
1 
22 #ifndef PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
23 #define PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
24 
26 
27 #include <algorithm>
28 #include <iosfwd>
29 #include <map>
30 #include <stdexcept>
31 #include <string>
32 #include <sstream>
33 
35 
36 namespace phys {
37 
39 
40 namespace units {
41 
43 
44 struct quantity_error : public std::runtime_error
45 {
46  quantity_error( std::string const text )
47  : std::runtime_error( text ) { }
48 };
49 
51 
53 {
54  prefix_error( std::string const text )
55  : quantity_error( text ) { }
56 };
57 
59 
60 inline Rep prefix( std::string const prefix_ )
61 {
62  std::map<std::string, Rep> table
63  {
64  { "m", milli },
65  { "k", kilo },
66  { "u", micro },
67  { "M", mega },
68  { "n", nano },
69  { "G", giga },
70  { "p", pico },
71  { "T", tera },
72  { "f", femto },
73  { "P", peta },
74  { "a", atto },
75  { "E", exa },
76  { "z", zepto },
77  { "Z", zetta },
78  { "y", yocto },
79  { "Y", yotta },
80  { "h", hecto },
81  { "da", deka },
82  { "d", deci },
83  { "c", centi },
84  { "r", ronto },
85  { "q", quecto },
86  { "R", ronna },
87  { "Q", quetta },
88  };
89 
90  auto pos = table.find( prefix_ );
91 
92  if ( pos == table.end() )
93  {
94  throw prefix_error( "quantity: unrecognized prefix '" + prefix_ + "'" );
95  }
96 
97  return pos->second;
98 }
99 
106 template <typename Dims>
107 struct unit_info
108 {
110 
111  static bool single()
112  {
113  return Dims::is_base;
114  }
115 
117 
118  static std::string name()
119  {
120  return symbol();
121  }
122 
124 
125  static std::string symbol()
126  {
127  std::ostringstream os;
128 
129  bool first = true;
130 
131  emit_dim( os, "m", Dims::dim1, first );
132  emit_dim( os, "kg", Dims::dim2, first );
133  emit_dim( os, "s", Dims::dim3, first );
134  emit_dim( os, "A", Dims::dim4, first );
135  emit_dim( os, "K", Dims::dim5, first );
136  emit_dim( os, "mol", Dims::dim6, first );
137  emit_dim( os, "cd", Dims::dim7, first );
138  emit_dim( os, "eV", Dims::dim8, first );
139 
140  return os.str();
141  }
142 
144 
145  static void emit_dim( std::ostream & os, const char * label, int exp, bool & first )
146  {
147  if( exp == 0 )
148  return;
149 
150  if ( first )
151  first = false;
152  else
153  os << " ";
154 
155  os << label;
156 
157  if( exp > 1 )
158  os << "+";
159 
160  if( exp != 1 )
161  os << exp;
162  }
163 };
164 
165 }} // namespace phys::units
166 
167 #include "quantity_io_meter.hpp"
168 #include "quantity_io_kilogram.hpp"
169 #include "quantity_io_second.hpp"
170 #include "quantity_io_ampere.hpp"
171 #include "quantity_io_mole.hpp"
172 #include "quantity_io_candela.hpp"
173 
174 /*
175  * User must choose celsius or kelvin, either by defining
176  * QUANTITY_USE_CELSIUS or QUANTITY_USE_KELVIN, or by
177  * including the desired include file.
178  */
179 #if defined(QUANTITY_USE_CELSIUS) && defined(QUANTITY_USE_KELVIN)
180 # error At most define one of QUANTITY_USE_CELSIUS, QUANTITY_USE_KELVIN
181 #endif
182 #ifdef QUANTITY_USE_CELSIUS
183 # include "quantity_io_celsius.hpp"
184 #endif
185 #ifdef QUANTITY_USE_KELVIN
186 # include "quantity_io_kelvin.hpp"
187 #endif
188 
189 namespace phys { namespace units {
190 
192 
193 template< typename Dims, typename T >
194 std::string to_magnitude( quantity<Dims, T> const & q )
195 {
196  std::ostringstream os;
197  os << q.magnitude();
198  return os.str();
199 }
200 
202 
203 template< typename Dims, typename T >
204 std::string to_unit_name( quantity<Dims, T> const & /* q */)
205 {
206  return unit_info<Dims>::name();
207 }
208 
210 
211 template< typename Dims, typename T >
212 std::string to_unit_symbol( quantity<Dims, T> const & /* q */)
213 {
214  return unit_info<Dims>::symbol();
215 }
216 
218 
219 inline std::string to_string( long double const value )
220 {
221  std::ostringstream os;
222  os << value;
223  return os.str();
224 }
225 
227 
228 namespace io {
229 
231 
232 template< typename Dims, typename T >
233 std::ostream & operator<<( std::ostream & os, quantity<Dims, T> const & q )
234 {
235  return os << q.magnitude() << " " << to_unit_symbol( q );
236 }
237 
239 
240 template< typename Dims, typename T >
241 std::string to_string( quantity<Dims, T> const & q )
242 {
243  std::ostringstream os;
244  os << q;
245  return os.str();
246 }
247 
248 } // namespace io
249 
250 }} // namespace phys::units
251 
252 #endif // PHYS_UNITS_QUANTITY_IO_HPP_INCLUDED
253 
254 /*
255  * end of file
256  */
std::string to_magnitude(quantity< Dims, T > const &q)
magnitude as string.
quantity error base class (not used by quantity itself).
Definition: quantity_io.hpp:44
candela, fundamental dimension.
std::string to_unit_name(quantity< Dims, T > const &)
unit name.
std::string to_unit_symbol(quantity< Dims, T > const &)
unit symbol.
namespace phys.
Zero-overhead dimensional analysis and unit/quantity manipulation and conversion. ...
meter, fundamental dimension.
kilogram, fundamental dimension.
static std::string symbol()
provide unit&#39;s symbol.
std::string to_string(long double const value)
string representation of value.
Rep prefix(std::string const prefix_)
return factor for given prefix.
Definition: quantity_io.hpp:60
class "quantity" is the heart of the library.
Definition: quantity.hpp:54
constexpr value_type magnitude() const
the quantity&#39;s magnitude.
Definition: quantity.hpp:346
static bool single()
true if base dimension.
Provide SI units-and-exponents in as close to NIST-specified format as possible with plain ascii...
ampere, electrical current, a fundamental dimension.
celsius, thermodynamic temperature.
static void emit_dim(std::ostream &os, const char *label, int exp, bool &first)
emit a single dimension.
prefix error, e.g. when prefix is unrecognized.
Definition: quantity_io.hpp:52
second, fundamental dimension.
static std::string name()
provide unit&#39;s name.
kelvin, fundamental dimension.